为什么十进制数不能完全用二进制表示? [英] Why can't decimal numbers be represented exactly in binary?

查看:378
本文介绍了为什么十进制数不能完全用二进制表示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关于浮点表示的问题已经有了几个问题。例如,十进制数字0.1没有精确的二进制表示,所以使用==运算符将其与另一个浮点数字进行比较是危险的。我明白浮点表示背后的原理。



我不明白的是,从数学的角度来看,为什么是小数点右边的数字例如,数字61.0有一个确切的二进制表示,因为任何数字的整数部分总是精确的。但数字6.10不是确切的。我所做的只是把小数点后移一位,突然间我从Exactopia变成了Inexactville。在数学上,这两个数字之间应该没有内在的区别 - 它们只是数字。



相比之下,如果我将小数点位置移到另一个方向产生数字610,我仍然在Exactopia。我可以继续沿着这个方向(6100,610000000,610000000000000),他们仍然是确切的,确切的,确切的。但是一旦小数点超过某个阈值,这些数字就不再准确。

发生了什么事?



编辑:为了澄清,我想远离关于IEEE等行业标准表示的讨论,坚持我认为是数学上的纯的方式。在基数10中,位置值是:

  ... 1000 100 10 1 1/10 1/100 ... 

在二进制中,它们是:

  ... 8 4 2 1 1/2 1/4 1/8 ... 

这些数字也没有任何限制。

解决方案

十进制数可以 完全表示,如果你有足够的空间 - 只是不浮点二进制点数。如果你使用浮点十进制点类型(例如.NET中的 System.Decimal ),那么很多值不能完全用二进制表示浮点可以被精确地表示。



让我们从另一个角度来看 - 在基数10中,您可能会感到满意,但不能准确表达1/3。这是0.3333333 ...(经常性)。您不能将0.1表示为二进制浮点数的原因完全是由于相同的原因。你可以完全表示3,9和27,但不能是1/3,1/9或1/27。问题是,3是一个素数这不是10的因素。当你想把一个数乘以3时,这不是问题:你总是可以乘以一个整数而不会遇到问题。但是,如果你用一个数字来区分一个数字,而这个数字不是你的基数,那么你可能会遇到麻烦(如果你试图将1除虽然0.1通常被用作精确十进制数的最简单的例子,但它不能完全用二进制浮点数表示,可以说0.2是一个更简单的例子,因为它是1/5 - 5是导致十进制和二进制之间的问题的主要元素。






处理有限表示的问题:



一些浮点小数点类型具有固定大小,如 System.Decimal others像> java.math.BigDecimal 是任意大 - 但是它们会在某个时刻达到一个极限,无论是系统内存还是理论上的最大数组大小。然而,这与这个答案的主要部分完全是分开的。即使你有一个真正的大量的位来玩,你仍然不能精确地表示浮点二进制表示的十进制0.1。与其他方式比较:给定任意数量的小数位数,您可以

There have been several questions posted to SO about floating-point representation. For example, the decimal number 0.1 doesn't have an exact binary representation, so it's dangerous to use the == operator to compare it to another floating-point number. I understand the principles behind floating-point representation.

What I don't understand is why, from a mathematical perspective, are the numbers to the right of the decimal point any more "special" that the ones to the left?

For example, the number 61.0 has an exact binary representation because the integral portion of any number is always exact. But the number 6.10 is not exact. All I did was move the decimal one place and suddenly I've gone from Exactopia to Inexactville. Mathematically, there should be no intrinsic difference between the two numbers -- they're just numbers.

By contrast, if I move the decimal one place in the other direction to produce the number 610, I'm still in Exactopia. I can keep going in that direction (6100, 610000000, 610000000000000) and they're still exact, exact, exact. But as soon as the decimal crosses some threshold, the numbers are no longer exact.

What's going on?

Edit: to clarify, I want to stay away from discussion about industry-standard representations, such as IEEE, and stick with what I believe is the mathematically "pure" way. In base 10, the positional values are:

... 1000  100   10    1   1/10  1/100 ...

In binary, they would be:

... 8    4    2    1    1/2  1/4  1/8 ...

There are also no arbitrary limits placed on these numbers. The positions increase indefinitely to the left and to the right.

解决方案

Decimal numbers can be represented exactly, if you have enough space - just not by floating binary point numbers. If you use a floating decimal point type (e.g. System.Decimal in .NET) then plenty of values which can't be represented exactly in binary floating point can be exactly represented.

Let's look at it another way - in base 10 which you're likely to be comfortable with, you can't express 1/3 exactly. It's 0.3333333... (recurring). The reason you can't represent 0.1 as a binary floating point number is for exactly the same reason. You can represent 3, and 9, and 27 exactly - but not 1/3, 1/9 or 1/27.

The problem is that 3 is a prime number which isn't a factor of 10. That's not an issue when you want to multiply a number by 3: you can always multiply by an integer without running into problems. But when you divide by a number which is prime and isn't a factor of your base, you can run into trouble (and will do so if you try to divide 1 by that number).

Although 0.1 is usually used as the simplest example of an exact decimal number which can't be represented exactly in binary floating point, arguably 0.2 is a simpler example as it's 1/5 - and 5 is the prime that causes problems between decimal and binary.


Side note to deal with the problem of finite representations:

Some floating decimal point types have a fixed size like System.Decimal others like java.math.BigDecimal are "arbitrarily large" - but they'll hit a limit at some point, whether it's system memory or the theoretical maximum size of an array. This is an entirely separate point to the main one of this answer, however. Even if you had a genuinely arbitrarily large number of bits to play with, you still couldn't represent decimal 0.1 exactly in a floating binary point representation. Compare that with the other way round: given an arbitrary number of decimal digits, you can exactly represent any number which is exactly representable as a floating binary point.

这篇关于为什么十进制数不能完全用二进制表示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆