Convert float to int without float initialization (mantissa)

I'm working on project where size of sketch is very important. So I can not afford to use FLOAT math. But in my code I have ONLY one float variable that I really need. All that this variable do is :

float Vpp;
int V_min, V_max;

Vpp = (V_max - V_min) * 50.0 / 255;

u8g.print(Vpp); // Its print on the display using u8glib

Maybe someone know how to replace FLOAT with INT, without any FLOAT initialization. Maybe somehow extract the mantissa and write FLOAT number like two INT. Or maybe someone know some formula.

Using one float already links a lot of code/libs. (you did use two, Vpp + 50.0)
What you apparently want is to print a value as if it was a float.

what is the max value of Vpp

this sketch shows how to do it for 3 decimals, given a certain range.
It moves the math to 32 bit longs, (unit is 1/1000 Volt)

Should be easily adaptable to 1 or 2 decimals

note the L suffix means LONG and forces 32 bit math.

void setup()
{
  Serial.begin(115200);
  Serial.print("Start ");
  Serial.println(__FILE__);

  int V_min = 2073;
  int V_max = 5044;

  // METHOD 1
  float Vpp = (V_max - V_min) * 50.0 / 255;
  Serial.println(Vpp, 3);

  // METHOD 2
  long lVpp = (V_max - V_min) * 196078L;  // magic number 196078 = 50/255 * 1000000L 
  Serial.println(lVpp );
  int whole   = lVpp / 1000000L;
  int decimal = (lVpp - whole * 1000000L + 500L) / 1000L;   // + 500 is for proper rounding

  Serial.print(whole);
  Serial.print(".");
  if (decimal < 100) Serial.print("0");  // do not forget leading zeros
  if (decimal < 10) Serial.print("0");
  Serial.println(decimal);
}

void loop()
{
}

in above sketch max value for Vpp (temp) can be around 1000 ~ 1.000 Volt
if range need to be larger you might reduce decimals.

Not satisfied with results, I wrote a method 3 to support a larger range of voltages.
Also put it in loop to test more values

void setup()
{
  Serial.begin(115200);
  Serial.print("Start ");
  Serial.println(__FILE__);
}

void loop()
{
  // BETWEEN 0..1 and 0..10 Volt
  int V_min = random(1000);
  int V_max = V_min + random(9000);

  // METHOD 1
  float Vpp = (V_max - V_min) * 50.0 / 255;
  Serial.print(Vpp, 3);
  Serial.print("\t");

  // METHOD 2
  long temp   = (V_max - V_min) * 196078L;  // 196078 = 50/255 * 1000000
  // Serial.println(temp);
  int whole   = temp / 1000000L;
  int decimal = (temp - whole * 1000000L + 500L) / 1000L; // rounding

  Serial.print(whole);
  Serial.print(".");
  if (decimal < 100) Serial.print("0");
  if (decimal < 10) Serial.print("0");
  Serial.print(decimal);
  Serial.print("\t");

  // METHOD 3 -
  temp   = (V_max - V_min) * 50L;
  // Serial.println(temp);
  whole   = temp / 255L;
  decimal = ((temp - whole * 255L) * 392L + 50) / 100L;

  Serial.print(whole);
  Serial.print(".");
  if (decimal < 100) Serial.print("0");
  if (decimal < 10) Serial.print("0");
  Serial.println(decimal);
  Serial.println();

  delay(100);
}

give it a try

Amazing, thanks. I will test it now.

Can you explain the factors 50 and 255 in your formula?

WOW. Your code working properly. AMAZING. Thanks. This example need to be on FAQ of official site.

I cant explain you the code, because its not mine. Its oscilloscope sketch. You can find whole code there :

I'm just trying to optimize code size. And I'm already reduced 3-4kb.

Why not just use millivolts instead of volts? Then no need for decimal places.

robtillaart:

  // METHOD 2

long temp  = (V_max - V_min) * 196078L;  // 196078 = 50/255 * 1000000
  // Serial.println(temp);
  int whole  = temp / 1000000L;
  int decimal = (temp - whole * 1000000L + 500L) / 1000L; // rounding

You forgot about the carry.
You need:

if (decimal>999) {
  decimal = 0;
  whole++;
}

or something of that sort.