some kind of overflow

I’m trying to scale the analog input (0-1023) to a bargraph of 90 pixels on a TFT so I thought it would be simple to calculate this.

I don’t understand why the calculation (balk = 90 * oude_potmet / 1023) goes wrong when “oude_potmet” exceeds 364.
The workaround is simple (balk = 0.0879765395894490 * oude_potmet) but I would like to know what goes wrong.

I you run the code and take a look in the serial monitor you will see what goes wrong, balk should increase to 90 but starting from oude_potmet = 365, balk decreases again

I am using IDE 1.6.3, but same result in older versions.

float balk;

void setup() {
  Serial.begin(9600);

  for (int oude_potmet = 0; oude_potmet < 1024 ; oude_potmet++)
  {
    Serial.print("oude_potmet = "); 
    Serial.print(oude_potmet);
    balk = 90 * oude_potmet / 1023 ;  // DOES NOT WORK, OVERFLOW WHEN oude_potmet exceeds 364

//    balk = 0.0879765395894490 * oude_potmet;  // WORKS FINE for all values of oude_potmet
    Serial.print("   balk = "); 
    Serial.println(balk);
   
  }

}

void loop() {

}

luxxtek:
I don't understand why the calculation (balk = 90 * oude_potmet / 1023) goes wrong when "oude_potmet" exceeds 364.

To avoid integer overflow, do "long" calculation:

balk = 90L * oude_potmet / 1023;

I was going to suggest making the numeric constants in the calculation into floats rather than ints.

balk = 90.0 * oude_potmet / 1023.0 ;

90L does indeeds solve the problem but I don't understand why there is an integer overflow if balk is a float ?

UKHeliBob:
I was going to suggest making the numeric constants in the calculation into floats rather than ints.

balk = 90.0 * oude_potmet / 1023.0 ;

this does not work

Balk may be a float, but that only matters after all the math on the right is finished. The stuff on the right of the equals are all ints so it is all done with int math.

luxxtek:
90L does indeeds solve the problem but I don't understand why there is an integer overflow if balk is a float ?

Even if 'balk' is float, but '90 * oude_potmet' is int, because int multiplied by int = int.

And max. int with 8bit controllers is 32767 only!
Your integer overflow is in the interim calculation.

Thanks for the explanation, I thought (hoped) that because a float was involved in the calculation, all numbers would be treated as float to keep accuracy at max.
But unfortunately it is not the case.

But a float wasn't involved in the calculation. The calculation in the code you posted was all ints. The only thing involving a float was that you tried to put the result into one. But that assignment happens after the calculation is all done.

Had a float been involved in the calculation then the calculation would have been done with floating point math.

Had a float been involved in the calculation then the calculation would have been done with floating point math.

Hence my suggested solution in reply #2 of which the OP said "this does not work".

luxxtek:
Thanks for the explanation, I thought (hoped) that because a float was involved in the calculation, all numbers would be treated as float to keep accuracy at max.
But unfortunately it is not the case.

Expressions are evaluated in a specific order, and arguments will be promoted to a different type, if necessary, as the expression is evaluated. The exact ORDER of evaluation can be tricky, so it is always best to use parentheses to make your intent explicit.

In the case where an integer expression is used to initialize a float, the conversion to float will occur only AFTER the expression has been fully evaluated. So, you should coerce the operands to float to ensure you get the result you want. In the following expression:

int x  = 5;
int y = 10;
float z = 20.0;

float a = z + x * y;

First, x and y will be multiplied as integers, THEN the result will be converted to float, and multiplied by z, with the result that a = 70.0 as you'd expect. But:

int x  = 5;
int y = 10;
float z = 20.0;

float a = z + x / y;

In this case, x will be divided by y, as integers, which results in 0. This is converted to a float, and added to z, with the result that a = 20.0. Not what you might expect. This can be fixed by casting either x or y to float:

int x  = 5;
int y = 10;
float z = 20.0;

float a = z + (float)x / y;

This will then convert BOTH x and y to floats BEFORE the divide, and a will end up 20.5 as you'd expect.

Now, of course, your other problem is you were multiplying 90 * 1023, which is too large to fit into an int...

Regards,
Ray L.

UKHeliBob:
Hence my suggested solution in reply #2 of which the OP said “this does not work”.

thanks for the suggestion, I did try but it does not work, it adds 2 decimals but still the overflow occurs.

luxxtek:
thanks for the suggestion, I did try but it does not work, it adds 2 decimals but still the overflow occurs.

You must multiply with 90.0 and not with 90!

By multiplying with 90.0 it is a floating point multiplication.
By multiplying with 90 it is an integer multiplication.

You must multiply with 90.0 and not with 90!

As I suggested.

luxxtek:
this does not work

Your posted code does not show 90.0 so don't say it doesn't work, please.

luxxtek:
Thanks for the explanation, I thought (hoped) that because a float was involved in the calculation, all numbers would be treated as float to keep accuracy at max.

Operators are applied in a sequence as defined by the order of operations in the C language.

Type conversions are applied (notionally) when they are required.

Performing type casts at the start would reduce accuracy, not improve it, because integer computation is always exact, whereas floating point involves a degree of loss of precision.

This becomes especially significant when up-converting signed quantities from smaller to longer integer values. Sometimes it is important to keep track of the effect of sign extension on what you are doing.