Multiplication bug

Good morning!

Can anybody explain to me why the return value of t is -8.311896E7?

imagen

There is a max value that a variable can have? I can’t understand why it is happening. I have read the reference guide of Processing, and a float number can store values between 3.40282347E+38 and -3.40282347E+38, so I don’t know where is the problem
Thanks
Thanks

Are we supposed to know the expected value? :roll_eyes:

float f = 1920*1080*2000 / 1920*1080;
println(f); // -8.311896E7

double d = 1920*1080*2000d / 1920*1080;
println(d); // 2.3328E9

int i = 1920*1080*2000 / 1920*1080;
println(i); // -83_118_960

long l = 1920*1080*2000L / 1920*1080;
println(l); // 2_332_800_000

println(d == l); // true

exit();

Thanks for the reply. No, the value should be extracted from the screen’s dimension, so It is not supposed to be known, this was just a fast test. I have try the same code with 3 different values and it works. I can’t understand why It is happening, calculatedDimension2 is 2000 now.

imagen

Discourse.Processing.org/faq#format-your-code

Sorry, I will put wirte my code formatted next time:

float calculatedDimension0=0;
float calculatedDimension1=0;
float calculatedDimension2=0;

void setup() {
  size(displayWidth, displayHeight);
calculatedDimension0=width*height;
calculatedDimension1=calculatedDimension0*2000;
calculatedDimension2=calculatedDimension1/(1920*1080);
  println(calculatedDimension2); //now is 2000 the value wich is correct
}

I tried before with long and double types, but the results were still wrong

void setup() {

  float t= 1920*1080*2000/1920*1080;
  println(t); //-8.311896E7

  double t1= 1920*1080*2000/1920*1080;
  println(t1); //-8.311896E7

  long t2= 1920*1080*2000/1920*1080;
  println(t2); //-83118960
}

I don’t understand why the value is not the correct one if I only use one variable instead of 3 like in the first case.

Thank you @GoToLoop for your help

float t = 1920*1080*2000 / 1920*1080;
println(t); // -8.311896E7

double t1 = 1920*1080*2000d / 1920*1080;
println(t1); // 2.3328E9

long t2 = 1920*1080*2000L / 1920*1080;
println(t2); // 2_332_800_000

exit();

Ok, if you add the d (in case of the double) or L in the long type, the values change, but any of them are still the correct one, 2000. Is there something I am missing? Sorry if I am doing very simple questions and I am very grateful of your support @GoToLoop

  • You can place the qualifier suffix d or l on any literal value.
  • But do it before the current operation results in a value too big.
  • It doesn’t need to be exactly on the value 2000, but can’t be after 2000.
  • You can also suffix all of them if you prefer.
1 Like

In this statement, from the original post, which numbers are intended to be in the denominator?

  float t= 1920*1080*2000/1920*1080;

There’s 2 things going on here.

Although the variable t is a float, the calculation 1920*1080*2000 / 1920*1080 seems to calculate into an intermediate integer type (as all the values in the calculation are integers).

This value seems to be overflowing the integer type (as 2.3328E9 > 2^31 − 1) before being passed back as a float to t.

You can force float calculation by explicitly making any one of the values a float: 1920.0 or 1920f for example.

 float t = 1920f*1080*2000/1920*1080; // 2.3328E9

Now we get the correct answer.

Once we correct for above, there’s another problem – you’re not getting your expected result of 2000. This is because of the order of operations:

Java is effectively calculating this:

1920*1080*(2000/1920)*1080

whereas you want this:

1920*1080*2000/(1920*1080)

And now…

float t = 1920f*1080*2000/(1920*1080); // 2000.0
4 Likes
float t = 1920*1080*2000 / (1920*1080);
println(t); // -8.311896E7

double t1 = 1920*1080*2000d / (1920*1080);
println(t1); // 2000.00

long t2 = 1920*1080*2000L / (1920*1080);
println(t2); // 2000

:wink:

2 Likes

So the expected value is 2000 but you replied to me there wasn’t 1. O_o

Thanks a lot for all the answers! That’s the key :
This value seems to be overflowing the integer type (as 2.3328E9 > 2^31 − 1) before being passed back as a float to t .

Just doing what @GoToLoop told me in the comment before is solved, adding the suffix or just forcing the calculation adding .00 at the end of the number.

Thanks!

Sorry if I have explained myself wrong @GoToLoop . The value has to be 2000 in this case of course! (cause we are multiplying and dividing with the same number) I want to make the script responsive, so I tried to create a value that resizes itself depending on the screen. Just for testing purposes, I am using the 1920x1080 value in the equation, but it will be :

float t= width*height*2000f/(1920*1080);

Thanks
:blush:

I was curious about how exactly the overflow (leading to an answer of -83118960) was behaving so I looked into what was happening.

Let’s first break up the expression into 3 parts to better understand the behaviour as Java evaluates it:

t = 1920*1080*2000/1920*1080

is equivalent to

t = 1920*1080*2000 // a
t/= 1920 // b
t*= 1080 // c

a) Overflow

1920*1080*2000 evaluates to 4147200000, which is greater than Java’s 32 bit signed integer limit (2147483647) so an overflow happens, which behaves as follows:

First know that 2147483647 + 1 evaluates (wraps around) to -2147483648, because the sign bit gets flipped from 0 to 1 and all other digits roll over to zero (10000000 00000000 00000000 00000000). And now, as the bits count up, the number becomes less negative (Two’s complement).

The point above can be generalised to 2147483647 + N = -2147483648 + (N-1)

Coming back to our number, its “raw overflow”, N, is 4147200000-2147483647 = 1999716353.

So, at this stage the temporary result is -2147483648 + (1999716353-1) = -147767296 (note this is the same as 4147200000-(2^31)*2).

b) Integer Division

Now Java computes the result from before (-147767296) divided by 1920.

Working with floats, this would equal -76962.1333. However, as both numbers are integers, Java performs integer division, so the result is automatically rounded towards 0.

So, at this stage the temporary result is -76962.

c) Multiplication

Finally, -76962 is multiplied by 1080.

The result? -83118960, a.k.a. -8.311896E7.

3 Likes

It’s not rounded but truncated. That is, everything after the decimal point is simply removed. :nerd_face:

So there can be some discrepancies on the result depending on the signum of the operands: :heavy_plus_sign: :heavy_minus_sign:

int rounded, truncated;

rounded = round(11 / 2.0);
println(rounded); // 6

truncated = 11 / 2;
println(truncated); // 5

rounded = round(-11 / 2.0);
println(rounded); // -5

truncated = -11 / 2;
println(truncated); // -5

exit();

:wink:

1 Like