NumberValue can't be 0.4, it changes to 0.39999999999

Title says all, it just looks ugly, why can’t it just be 0.4?

5 Likes

I think it’s because of how numbers after the decimal are stored. I heard sometime ago (not sure if it’s actually true, someone confirm this for me please) that numbers after the decimal are stored in fractions of 1/2^x. This means 0.5 would be stored as 1/2, 0.75 would be stored as 1/2 + 1/4, 0.825 would be 1/2 + 1/4 + 1/8 and so on. It’s basically the opposite of how whole numbers (ints) are stored, where 21 == 16+4+1 == ‘10101’.

As a result, there is no way to get the number 0.4 exactly as it consists out of 1/4 + 1/8 + 1/64 + … etc. until you run out of bits. Depending on how much bits are reserved for saving a number, the closer you can get to 0.4, but you will never reach the exact number.

2 Likes

Well if this is true I dont expect them to fix this. But really tho, that’s pretty bad way of storing numbers.

But then you can save much more numbers on less bits!!

I havn’t seen any other program have this issue.
I am certain that the majority of people using NumberValues are using it with values within the range of 0-200, just a fraction would use if for huge numbers.

I use string values and tonumber to solve this.

1 Like

You wont find an engine that does not use floats for everything

1 Like

http://floating-point-gui.de/basic/

1 Like

Thing is, these things could be avoided if you just round off the last 0.00001 digit.

I think that should be up to the developer

1 Like

Not quite. The computer would be lying to you.

And with lots of calculations that rounding results in larger and larger errors.

3 Likes

True that but consider this:
First off, if you’re doing astronomical calculations using a VectorValue instead of doing it directly in a script then you’re doing it wrong.

Secondly, we eventually reach a point at which we can’t get precise values such as 0.3.
You are already rounding that value off by setting it to: 0.29999999999999999

Thirdly I can’t change 0.29999999999999999 to 0.29999999999999998 which kinda defeats the point of having that many decimals.

You should read the Wikipedia article that someone posted above. It explains why everything you’re arguing for can’t happen.

Long story short, floating point numbers aren’t represented with the actual decimals. The number of digits in the representation you see is arbitrary.

The problem you’re describing is an inherent limitation of how floating point numbers work, and it is the reason why your parts can sometimes drift apart after moving unwelded models around with the Studio tools. Yes, the more mathematical operations you do on them, the more the error builds up.

However, representing them like you’re asking would introduce even more error than before. This might seem counterintuitive, since you obviously wanted 0.3 and not 0.2999999… but there’s no way to determine what you actually wanted. What if you really did want 0.2999999999? Yes, you could keep around a perfectly exact representation, but instead of four bytes, you’re using a byte for each digit. That adds up incredibly quickly and your place files would be hundreds of megabytes, maybe even gigabytes.

Anyway, here’s some perspective on this. JPL often needs the value of pi in orbital calculations for their spacecraft. How many digits do you think they use? It’s less than you think.

They use 3.141592653589793.

2 Likes

May have already been said, but you can’t store 0.4 in binary, just like you can’t store 1/3 in decimal. What it shows you is the accurate value the computer sees (and it’s not too far off). Maybe there should be an epsilon value that rounds the value that’s displayed to the user in Studio, though? With a hovered tooltip showing the true value? Dunno, this has bothered me before but knowing that it is impossible to have 0.4 accurately stored as binary makes it better.

Yes pls
C languages have Double.Epsilon and Float.Epsilon, I don’t see how that couldn’t be exposed to Lua

This is C#, right? C++ doesn’t have that, C# is more similar to Java than C/C++. I really don’t like the idea of adding an epsilon value to all floating point comparisons in ROBLOX Lua, especially because it isn’t really easy to implement internally. The number type in Lua is implemented with a fundamental type (double), not a class. So there isn’t an easy way to add an epsilon to every number comparison.

I also don’t think hiding the true representation of floating point values in Studio UI is a good idea, if the numbers always display as rounded this will make developers confused when comparing floating point values fails.

C++ has

numeric_limits<float>::epsilon

which is a part of limits.h

edit:
Also I wasn’t suggesting adding it to internal comparisons, only as a value readable in Lua that developers could use,
so just exposing the epsilon as a global in the lua state maybe

I just wouldn’t support masking something like this from devs. Show the numbers the way they are. If a developer is ever uncertain as to why this is, we can teach them. I think that’s much better than hiding it from them which will really only come to trouble them later in their programming career.

6 Likes

But I wasn’t at any point suggesting to round the numbers internally? Only to give developers access to the epsilon.
I mean sure anyone can decide exactly how accurate they want their float comparisons to be, but having a “default epsilon” is a nice guideline

Floating numbers are such a fun thing:

print(111111111111111321==111111111111111330) --> true
6 Likes