Jump to content
Posted 07 August 2014 - 07:56 AM
Posted 07 August 2014 - 08:10 AM
#1 What does it actually mean when it says 7.22 (i'll just take it as 7) decimal digits ?
A single-precision float with 24 effective bits (23 explicit and 1 implicit bit) has log10 224 = 24 log10 2 = 7.22, which is approximately 7, digits of precision. Note that it is not 7 decimal digits after the decimal point, but significant digits; the precision is relative, not absolute.
#2 What is the absollutely safe range (maximum and minimum) in floats without losing information(end ressult the number will be represented exactly). And how to safely use it?
Depends entirely on what scale you work with and type of operations you do.
If you limit yourself to integers, you can work with integers between -223 and +223 safely. If you introduce fractional powers of two, you need to ensure that the fractions don't scale beyond your 24 bits of precision.
For arbitrary values and operations, there's no such thing as "no loss of information" in floating point values.
Edited by Brother Bob, 07 August 2014 - 08:11 AM.
Posted 07 August 2014 - 08:36 AM
Those 7.22 decimal digits are important. Remember you are dealing with both accuracy and precision.
Floating point numbers work in base 2, not base 10. The decimal value 0.1 cannot be directly represented in base 2. It becomes binary 0.0001100011000111000111... That value is within the specified precision and is considered an accurate conversion.
That binary value of the decimal 0.1 is precise enough for 16 decimal places, converting back to decimal gives roughly 0.099999999999999972. So while it is accurate within the required precision of 7 decimal digits, it is not perfectly equal.
Also note that while the floating point standard requires 7 digits, the C++ language standard for numeric limits specifies 6 for the "number of digits, q, such that a floating-point number with q decimal digits can be rounded into a floating-point representation and back without loss of precision." Visual Studio uses the same constant.
In other words, even though you have 7.22 digits going from decimal to binary, you only have 6 digits if you intend to go round trip and show the number back to a human in decimal.
It all gets back to those two rules:
1. Floating point numbers are approximations. (Consequences: Do not ever consider them as exact values. Always use range operations when testing for equivalence. They have a narrow range of precision, or significant figures. Etc.)
2. Floating point inaccuracies accumulate. (Consequences: Small errors accumulate when used repeatedly. Shifting scales can cause catastrophic precision loss. Etc.)
Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.
Also check out my personal website at bryanwagstaff.com, where I occasionally write about assorted stuff.
Posted 07 August 2014 - 09:58 AM
#2 What is the absollutely safe range (maximum and minimum) in floats without losing information(end ressult the number will be represented exactly).
Posted 07 August 2014 - 10:09 AM
Game Developer, C++ Geek, Dragon Slayer - http://seanmiddleditch.com
C++ SG14 "Games & Low Latency" - Co-chair - public forums
Wargaming Seattle - Lead Server Engineer - We're hiring!
Posted 07 August 2014 - 10:53 AM
Posted 07 August 2014 - 02:43 PM
You can represent any integer in the range [-2^24, 2^24]. You are also safe to add, subtract and multiply integers, without precision loss, as long as the answer lies within that same range. Dividing numbers will often lead to rounding errors.
To understand why just think of the example of 2/3 in base ten. Given a finite amount of memory, there is no way to store 0.66666666... because there are an infinite amount of sixes. There are ways to express six repeating in a finite amount of memory but floating point numbers don't do that, instead they only store a certain amount of digits before rounding the last digit.
One thing to keep in mind is that some decimal numbers may be repeating in binary whereas in decimal they are not. 0.1, for example cannot be represented exactly in a floating point number, instead it will end up being something like 0.10000000000000001. Some decimal number can fit perfectly inside a floating point number. The numbers 0.5, 0.25, 0.125 all can be perfectly represented in a floating point number. This is because they are a power of two, where the exponent is negative. 0.5 = 2^(-1), 0.25 = 2^(-2), 0.125=2^(-3) ect...
Any of these numbers that can fit in a floating point number can be safely added, subtracted, and multiplied without problems. So 0.5 * 16 == 8 holds true, but 0.1 * 10 != 1.
If you want to better understand floating point numbers I would recommend trying to convert some numbers by hand between decimal and binary floating point. Take a look at the wikipedia article on floating points to better understand them, but bottom of the article has an example on how to convert to floating point.