2

I've been reading about floating point types in java such as double. I've also been reading about converting fractions to binary and how to do it. I can do the math and find that representing 0.2 in binary is the following approximation:

0.00110011001100...

However 2 in binary is 10. So why can't I just say that 0.2 (base 10 ) is equivalent to 0.10 (base 2)?

I've read a similar question, but I'm still confused by this

Another example would be something like 5.8

101.110011001100...

Why couldn't we do: 101.1000 since 8 in binary is 1000

I understand that 0.10 and 0.1000 are the same, but in this context they would be separate.

Community
  • 1
  • 1
Spark323
  • 1,525
  • 2
  • 16
  • 27
  • 3
    Because 0.1 in base 2 is 0.5 (`1 / (2 ** 1)`) in base ten? Why would the binary number system be completely inconsistent with the decimal one? Under your system removing trailing zeroes would change the number, but you presumably know that 5.8 is (generally) the same as 5.8000 – jonrsharpe Jul 12 '16 at 18:19
  • 2
    You may have just reinvented [binary coded decimal](https://en.wikipedia.org/wiki/Binary-coded_decimal). – Patricia Shanahan Jul 12 '16 at 19:24
  • @PatriciaShanahan `Many non-integral values, such as decimal 0.2, have an infinite place-value representation in binary (.001100110011...) but have a finite place-value in binary-coded decimal (0.0010). Consequently, a system based on binary-coded decimal representations of decimal fractions avoids errors representing and calculating such values.` I think that was kind of what I was getting at. I realize through answers and more research why this isn't possible with java but had never heard of bcd. – Spark323 Jul 12 '16 at 19:34
  • 1
    @eric In Java, you should be using BigDecimal when you need exact representation of finite length decimal fractions. – Patricia Shanahan Jul 12 '16 at 21:26
  • I agree with @Patricia. In Java, use BigDecimal if you need exact decimal representations and almost unlimited (or well-defined, if you like) precision. – Rudy Velthuis Jul 12 '16 at 22:44

2 Answers2

3

Because this would be inconsistent with how number representations in different bases work:

If you have a binary number, say 1100.101 it is represented with base 2, so in order to convert it to base 10 you need to do the following:

... 2^3   2²   2^1  2^0  .  2^-1   2^-2   2^-3 ...
    1     1    0    0    .  1      0      1

which means you have 2^3 + 2² + 2^-1 + 2^-3 = the number in base 10.

Notice how the exponents always just decrease by one from left to right. So basically, when you move one digit to the right, you are dividing by your base, in this case by 2.

This is how numbers are represented in any given base B. For B you have

... B^3   B²   B^1  B^0  .  B^-1   B^-2   B^-3 ...

For your example it means that:

0.2 = 2 * 10^-1   //base 10 (= 0.2 in base 10)
0.2 = 2 * 2^-1    //base 2
0.1 = 1 * 10^-1   //base 10
0.1 = 1 * 2^-1    //base 2  (= 0.5 in base 10)

Which is why 0.2 in base 10 is not and cannot be 0.1 in base 2.

Also you even said yourself that 0.10 and 0.1000 would be different numbers in your representation. (Which not only doesn't make any sense but it would be a nightmare to any computer)

Keiwan
  • 8,031
  • 5
  • 36
  • 49
0

For the same reason that 1/3 is a non-terminating decimal in base 10, 0.2 or 1/5 is non-terminating in base 2. Note that the fractional part of a binary number works the same way as in base 10, where 0.1 in base 10 is 10^-1, and 0.1 in base 2 is 2^-1, or 0.5. Similarly, 0.01 in base 2 is 1/4 and 0.001 is 1/8. Because finite sums of powers of two can't equal fractions that aren't a power of two in their denominator, those numbers are non-terminating. In practical applications, this can cause problems with floating-point arithmetic giving unexpected results due to rounding. It's for this reason that equality tests with floating point numbers are best done within a margin of error, like 0.01%.

See also: Is floating point math broken?

Community
  • 1
  • 1
alter_igel
  • 6,899
  • 3
  • 21
  • 40