LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

I=4 But FLOOR(I)=3

Root / Programming Questions / [.]

HackTheWorldsCreated:
Well I'm pretty sure this is a bug. Apparently when you add .4 to a variable until it equals 4, the floor value is 3. I'm using an old 3DS and I don't know if this only happens in FOR loops. Can somebody else try this out to see if it happens to them? This code should reproduce the bug:
ACLS
FOR I = 2 TO 4 STEP .4
  PRINT "I=";I
  PRINT "FLOOR(I)=";FLOOR(I)
  PRINT
NEXT I
This is the output I get:
I=2
FLOOR(I)=2

I=2.6
FLOOR(I)=2

I=3.2
FLOOR(I)=3

I=3.6
FLOOR(I)=3

I=4
FLOOR(I)=3
As you can see that last output is really weird. (Edit: Fixed some typos. Thanks 12Me21.)

It happens for me too. I tried doing PRINT I*100000000 and the results were: 2000000000 2400000000 2800000000 4300000000 3599999999.99999994 3999999999.99999994 So it's a rounding error.

Ok. That's still kinda weird though considering it's 0.4. I wonder if it's just 0.4?

It's kind of weird how it does that... I'd expect something like that to happen with, say, .1 because you can't represent it fully with binary (that actually happened in PTC), but I don't know why it would happen with .4. Maybe you can't represent .4 entirely in binary? I think you can, but I'm not sure. At the very least, I'm surprised that it's not consistent with making it 3.9999999 and 3.

It turns out this isn't limited to .4 and 4. I can confirm it happens when adding 0.8 ten times (which should be 8) and when adding 0.1 ten times (which should be 1). They both produce a value just slightly under 8 and 1, resulting in the FLOOR value being one less than what it should be.

I guess you'll just have to use integers for your FOR loop steps, and divide the number Or add something really small like 0.0001 before FLOORing

The beauty of floating-point rounding errors, wew lads.

This is unfortunately a common error in a lot of languages. For example, in Haskell, I can make a list (array) starting from 0 until 1 incrementing by .1 each time by doing:
[0, 0.1 .. 1]
and the resulting list is:
[0.0, 0.1, 0.2, 0.30000000000000004, 0.40000000000000001, 0.50000000000000001, 0.60000000000000001, 0.70000000000000001, 0.8, 0.9, 1.0]
This gets really annoying. We need languages that prevent this kind of stuff from happening.

Store all variables in BCD!

This is unfortunately a common error in a lot of languages. For example, in Haskell, I can make a list (array) starting from 0 until 1 incrementing by .1 each time by doing:
[0, 0.1 .. 1]
and the resulting list is:
[0.0, 0.1, 0.2, 0.30000000000000004, 0.40000000000000001, 0.50000000000000001, 0.60000000000000001, 0.70000000000000001, 0.8, 0.9, 1.0]
This gets really annoying. We need languages that prevent this kind of stuff from happening.
That's too bad. And I agree. This shouldn't still be an issue with modern programming languages.

This is unfortunately a common error in a lot of languages. For example, in Haskell, I can make a list (array) starting from 0 until 1 incrementing by .1 each time by doing:
[0, 0.1 .. 1]
and the resulting list is:
[0.0, 0.1, 0.2, 0.30000000000000004, 0.40000000000000001, 0.50000000000000001, 0.60000000000000001, 0.70000000000000001, 0.8, 0.9, 1.0]
This gets really annoying. We need languages that prevent this kind of stuff from happening.
This isn't an issue with the language. Everything that implements a floating-point type, even double-precision, suffers from precision loss. This is simply how floating-point works: it tries to store an immense amount of decimal precision into only 64 bits (for doubles), so it has to take a sacrifice somewhere. The only way to circumvent this would be to put in better floating-point technology (better error correction, improve precision, make it so integers are always exact etc.) or forgo floating-point entirely in favor of infinite-accuracy math, which is far less efficient. EDIT: Reading this back, it's likely there's a bug in SB (or even in the 3DS system) that causes this rounding to work improperly, since I is said to be 4 even though flooring it is 3. Maybe two separate correction procedures are used for output versus rounding, and this is what's causing it.

Well hey what do you know, SmileBasic DID specify their limitations in the instruction manual this entire time! We can observe, but now nobody can complain :p http://smilebasic.com/en/reference/
FOR: Repeats the process for the specified number of times - The NEXT instruction should be placed at the end of the process - If the condition is not satisfied, the process may not be executed at all (omitted) - If the increment is specified as a fractional value, the intended loop count may not be achieved due to operational errors.