3

I have noticed my floats are giving me headaches for 2 specific numbers (32 and 128) and i don't fully understand whats going on with these 2 numbers, also not sure how to fix it.

I print out these 2 lines:

var resA = (int) Math.Floor((a - o) / 1.0f);
var resB = (int) Math.Floor((b - o) / 1.0f);

Here is some examples:

    var o = 0.795660f;

//test data
    var a = 31.795660f;
    var b = 32.795660f;
    Output: resA : 31, resB: 31 ???

    var a = 63.795660f;
    var b = 64.795660f;
    Output: resA : 63, resB: 64 // this is right

    var a = 127.795660f;
    var b = 128.795660f;
    Output: resA : 127, resB: 127 ???

Every other number up to 256 works fine except 32 and 128 (though there might be more numbers beyond that).

So why does 2^5 and 2^7 give me the wrong answer, but every other number i tried worked fine.. whats so special about these 2 numbers that makes it fail?

Additionally how do you generally fix this problem ?

WDUK
  • 1,412
  • 1
  • 12
  • 29
  • _"Additionally how do you generally fix this problem ?"_ - use a data type with more precision. – ProgrammingLlama Dec 18 '19 at 08:02
  • 1
    There is nothing wrong, it's just if you expect a number beeing 3,000000 you see the 'error' more obvious, than if you would expect to see 4.5834201. It has the very same error in it, just less visible, if you compute it with another number format maybe it's 4.5834202. There is no "only these two numbers", you cannot enumerate all existing numbers. If you are not satisfied with float, take another data-type, there would be double or decimal. – Holger Dec 18 '19 at 08:02
  • @John_ReinstateMonica i tried decimal and got the same issue...it didn't seem exclusive to floats.. – WDUK Dec 18 '19 at 08:03
  • 1
    The point here is, that floating-point-numbers are imprecise as per definition. That means `31.795660f - 0.795660f;` is **not** equal to 3, but more probably something like `2.999999999`. – MakePeaceGreatAgain Dec 18 '19 at 08:05
  • 1
    You asked, I quote: "why does 2^5 and 2^7 give me the wrong answer". The dupe clearly points that out. – MakePeaceGreatAgain Dec 18 '19 at 08:06
  • The answer is simple: float has 7 significant digits, you are using numbers with 8 and 9 digits. So this cannot work. – Holger Dec 18 '19 at 08:06
  • 1
    Firstly the duplicate doesn't talk about those 2 numbers specifically. Secondly... it doesn't suggest a fix for it. Doubles and decimals DID NOT fix the problem. You say its precision issues then why did 64 work fine ? – WDUK Dec 18 '19 at 08:06
  • 3
    If we would search for a dupe to the exact same parameters, we **never** would find any. As developer you should be able to abstract, this is see similarities to other questions. Of course double won´t fiyx the issue, as they are also floating-point-numbers. – MakePeaceGreatAgain Dec 18 '19 at 08:08
  • Right so is there a fix ? Because your link does not give an answer to fix it.. i need a hacky fix even if i don't get answers for why only 32 and 128 cause the problem. Decimals don't work so "use a data type of more precision" is not an answer. – WDUK Dec 18 '19 at 08:09
  • @Holger how is the accepted answer in that link answering why 64 will work but not 32 and 128 ? .... Like i already know floats are imprecise but wouldn't all numbers have similar imprecision, and i don't know how to work around it. – WDUK Dec 18 '19 at 08:10
  • 1
    Edit your question to something like "I know, that floats are imprescise (and in particular I read the post mentioned in the dupe)" in order to avoud answers that point into this direction. Then we may re-open.Rephrase it to "However I was wondering how I can circumvent this". – MakePeaceGreatAgain Dec 18 '19 at 08:11
  • 1
    @WDUK It cannot be fixed. If you want to make appe pie, you should not use cherries. Use another datatype than float !!! https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems – Holger Dec 18 '19 at 08:11
  • Working with `double` or even `decimal` **may** work, but there are still cases where you have inacurracies. Simple anser: you cannot ensure accuracy with floating-points. – MakePeaceGreatAgain Dec 18 '19 at 08:12
  • @WDUK for a fix, we would need to know what you are _actually_ trying to do. You only showed that you calcuate with floats and are not satisfied with the results. There is no immediate fix to your two code lines. But maybe you should ask "I want to calculate this and that, but can't do it with floating points...how to calculate this and that correctly?" – René Vogt Dec 18 '19 at 08:13
  • So how does any program that does similar to what im doing not have these issues, they clearly much include some kinda hacky fix to fudge the numbers. – WDUK Dec 18 '19 at 08:13
  • @RenéVogt im converting world points to grid points where the grid origin `o` is at some world point off from 0,0 – WDUK Dec 18 '19 at 08:13
  • They are floating point numbers. Nothing special about them being inprecise: https://www.youtube.com/watch?v=PZRI1IfStY0 – Christopher Dec 18 '19 at 08:14
  • @Christopher so is the hundreds other numbers inbetween 32 and 128... but no issues with them lol – WDUK Dec 18 '19 at 08:14
  • @WDUK That sounds like a game. Games - with a few exceptions - do. not. use. floats. They use integers where the Decimal places are shifted during output. – Christopher Dec 18 '19 at 08:15
  • @HimBromBeere error ranges? I might need more info on what that means. – WDUK Dec 18 '19 at 08:15
  • @Christopher a game with only integer world positions would be quite silly. – WDUK Dec 18 '19 at 08:15
  • @WDUK You are working at the edge of precision. You ask questions like "If 10 people jump out of the 10th floor, why do only 3 die" . The difference of a and b is not always 1.00000000000000000. It's as simple as that. There is no need to find out for which numbers it is, and for which is not. – Holger Dec 18 '19 at 08:15
  • @Holger so how far from the edge should i limit my numbers to avoid it ? – WDUK Dec 18 '19 at 08:16
  • 1
    @WDUK No, actually a game with float world positions is stupid. It would ruin any atempt to use Deterministic Lockstep. I have no idea how Space and Medival Engineers compesnate for using floats, but it is propably early design level. As in "we are building something with float math" early. – Christopher Dec 18 '19 at 08:16
  • Use a tolerances, e.g. not relying on exactly 3, but by using something like `if (2.999 <= result && result <= 3.0001)` – MakePeaceGreatAgain Dec 18 '19 at 08:17
  • 1
    @Christopher tell that to unity and unreal and cryengine and frostbite. All use floats because GPUs use floats. – WDUK Dec 18 '19 at 08:17
  • @WDUK Either they are not doing what you are claiming or they are not using Determinstic Lockstep. Floats are inherently not determinstic. While we tried to maintain that property, it did not fully realize. https://gafferongames.com/post/deterministic_lockstep/ | And as for GPUs: The images that are send to the Monitor and store on disks as sure as heck not float. But of course a difference of 1 over 65536 is not that important, as it is only colors to be seen by the human eye. – Christopher Dec 18 '19 at 08:20
  • @WDUK You should not avoid it, you should expect something different. Your expectation is wrong, not the computer. Do something like: (int) Math.Floor((b - o +0.000001) / 1.0f); That would help. Or Add 0.5 and use Round instead of Floor. This approaches the number from two sides. But you cannot enforce a 31.9999999 to be a 32.000000 or vice versa. It's your algorithm that says "If the result is 31.999999 I want 31 as result". Change your algorithm to change result. – Holger Dec 18 '19 at 08:21
  • @Holger ah okay adding a small number worked, thank you for providing a fix :) – WDUK Dec 18 '19 at 08:22
  • @Christopher why would you use deterministic lockstep for all games ? Thats a madness, RTS games need that but many do not - plus thats a network solution not all games are networked. – WDUK Dec 18 '19 at 08:22
  • @WDUK Most games are networked. And even for those that are not, a reliable and determinstic saving and restoring of the game state is important. Floats have never been precise. They are inprecise by design. In practice, they also have never been determinstic due to people messing up the FPU Hardware. | The vast majority of applications do not needs a range from "Size of the Universe" to "Size of a Atom". They need precision in math, first and foremost. – Christopher Dec 18 '19 at 08:51

0 Answers0