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

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

问题描述

已经向 SO 发布了几个关于浮点表示的问题.例如,十进制数 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?

例如,数字 61.0 具有精确的二进制表示,因为任何数字的整数部分总是精确的.但数字 6.10 并不准确.我所做的只是将小数点移动一位,突然间我从 Exactopia 转到了 Inexactville.从数学上讲,这两个数字之间应该没有本质区别——它们只是数字.

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.

相比之下,如果我将小数点向另一个方向移动一位以产生数字 610,我仍然处于 Exactopia.我可以继续朝那个方向前进 (6100, 610000000, 610000000000000) 而且它们仍然精确、精确、精确.但是一旦小数点越过某个阈值,数字就不再准确.

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.

怎么回事?

澄清一下,我想远离关于行业标准表示的讨论,例如 IEEE,并坚持我认为是数学上纯粹"的方式.在基数 10 中,位置值是:

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 类型(例如 .NET 中的 System.Decimal),则可以准确表示许多无法用二进制浮点精确表示的值.

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.

让我们换一种方式来看待它 - 在您可能会习惯的基数 10 中,您无法准确表达 1/3.它是 0.3333333...(重复出现).不能将 0.1 表示为二进制浮点数的原因完全相同.您可以准确地表示 3、9 和 27 - 但不能表示 1/3、1/9 或 1/27.

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.

问题是 3 是一个质数,它不是 10 的因数.当您想将一个数乘以 3 时,这不是问题:您总是可以乘以一个整数而不需要遇到问题.但是当你一个质数而不是你的底数的因数时,你可能会遇到麻烦(如果你试图除以 1,这样做按那个数字).

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).

虽然 0.1 通常被用作无法用二进制浮点精确表示的精确十进制数的最简单示例,但可以说 0.2 是一个更简单的示例,因为它是 1/5 - 并且 5 是导致两者之间出现问题的素数十进制和二进制.

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.

某些浮点小数点类型具有固定大小,如 System.Decimal 其他类型如 java.math.BigDecimal 是任意大"的;- 但它们会在某个时候达到限制,无论是系统内存还是数组的理论最大大小.但是,这与此答案的主要内容完全不同.即使您有真正任意大量的位可供使用,您仍然无法在浮点二进制小数点表示法中准确表示十进制 0.1.将其与相反的方式进行比较:给定任意数量的十进制数字,您可以精确地表示任何可以精确表示为浮点二进制小数点的数字.

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天全站免登陆