Started by Aug 07 2014 07:56 AM

,
6 replies to this topic

Posted 07 August 2014 - 08:10 AM

POPULAR

#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 log_{10} 2^{24} = 24 log_{10} 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 -2^{23} and +2^{23} 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

POPULAR

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

POPULAR

#2 What is the absollutely safe range (maximum and minimum) in floats without losing information(end ressult the number will be represented exactly).

That question doesn't make much sense. There is no entire range of real numbers that can be represented exactly. Here's a description of what can be represented:

From 1 to 2 you can represent anything in increments of 2^-23. So these numbers can be represented exactly:

1.00000000000000000000000

1.00000011920928955078125

1.00000023841857910156250

1.00000035762786865234375

1.00000047683715820312500

1.00000059604644775390625

1.00000071525573730468750

1.00000083446502685546875

1.00000095367431640625000

1.00000107288360595703125

1.00000119209289550781250

1.00000131130218505859375

...

1.99999904632568359375000

1.99999916553497314453125

1.99999928474426269531250

1.99999940395355224609375

1.99999952316284179687500

1.99999964237213134765625

1.99999976158142089843750

1.99999988079071044921875

2.00000000000000000000000

Between 2 and 4 the step is 2^-22, then between 4 and 8 the step is 2^-21 and so on. For numbers smaller than 1, it works similarly: Between 0.5 and 1 the step is 2^-24, between 0.25 and 0.5 the step is 2^-25, and so on.

That is a almost a full description of the situation. Of course there is a maximum number that can be represented and things are different for numbers very close to zero.

If in light of this explanation you still have a question, post it.

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

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

I think that's way too much information for the "For Beginners" forum. You might scare people off by drowning them in details.

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.

My current game project Platform RPG