-1

curious thing happen when tried to cast from int to float and backwards.

Primitive example code:

int val = 28218681; // val=28218681

float fVal = (float) val; // fVal=2.821868E+07

int val2 = (int) fVal; // val2=28218680

May somebody explain why conversion lost rightmost "1" from value?

Thank You Marius

Community
  • 1
  • 1
Marius G
  • 3
  • 1
  • 4
    I think you can find an answer to your question here, it's a different language but the same principles applys. https://stackoverflow.com/questions/30260769/converting-int-to-float-loses-precision-for-large-numbers-in-swift – JOSEFtw Nov 23 '18 at 13:12
  • See - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/float - Note the precision is _"~6-9 digits"_ meaning not all 8 digit integers can be accurately represented as floats. – PaulF Nov 23 '18 at 13:13
  • A `float` and and `int` both use 32 bits. However, an `int` can use ALL of those bits to represent its sign and value, whereas a `float` uses some of those bits for the floating point and mantissa which means it can't represent the same range of integer values - so it loses some precision. – Matthew Watson Nov 23 '18 at 13:16
  • Not an answer, but do use decimal over floats if you want precise fractions. – Janne Matikainen Nov 23 '18 at 13:21
  • The float type has 24 bits available to represent a value, int has 31 bits. So large values can't fit and have to be rounded. The first time you'll lose a bit is at 2^24+1 = 16777217, try it. Use double to get ahead, it can store 53 bits. Or decimal, 96 bits, equivalent to 28 decimal digits. – Hans Passant Nov 23 '18 at 13:35
  • @JanneMatikainen I would not call `2.821868E+07` a fraction. It is no more a fraction than `1E+30` is. But otherwise I agree with you. – Jeppe Stig Nielsen Nov 23 '18 at 13:46
  • @JeppeStigNielsen ah true, did not mean exactly fractions, but more precision when doing lets say financial or construction calculations. – Janne Matikainen Nov 23 '18 at 14:01
  • @JanneMatikainen But we confuse things by discussing another problem. His example is a whole number. Whether to use binary or decimal is a different question than whether you use a type that is "wide" enough to have the desired precision. If the asker had used [`decimal32`](https://en.wikipedia.org/wiki/Decimal32_floating-point_format) instead of `binary32`, he would have had __the exact same issue!__ Only the leading _seven_ decimal figures could be contained in the `decimal32`. His integer has _eight_ decimal figures. Same problem with decimal as with binary, for `28218681`. – Jeppe Stig Nielsen Nov 23 '18 at 14:12

1 Answers1

1

This was a comment to a now deleted answer:

The integer 28218681 can be written in binary as 1101011101001010100111001. Note that 25 digits are needed. Single precision has only 24 bits for its "mantissa" (including the implicit leading 1 bit). 24 is less than 25. Precision is lost. A single-precision representation "remembers" a number only by its leading 24 binary digits. That corresponds to roughly 7-8 decimal figures. Roughly. The integer 28218681 has just 8 figures, so the problem arises.


The lesson learned is, use a type that is "wide" enough to give the desired precision. For example a double precision number can hold the first ~16 decimal figures of a number.

This is not related to the discussion on whether to use a binary or a decimal format. Note that if the asker had used decimal32 instead of binary32 (another name for float), he would have had the exact same issue!

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181