浮点数不准确示例 [英] Floating point inaccuracy examples

查看:20
本文介绍了浮点数不准确示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您如何向仍然认为计算机无限聪明和准确的新程序员和外行解释浮点不准确性?
您是否有一个最喜欢的例子或轶事似乎比精确但枯燥的解释更能传达这个想法?
这在计算机科学课程中是如何教授的?

How do you explain floating point inaccuracy to fresh programmers and laymen who still think computers are infinitely wise and accurate?
Do you have a favourite example or anecdote which seems to get the idea across much better than an precise, but dry, explanation?
How is this taught in Computer Science classes?

推荐答案

人们在使用浮点数时会遇到两个主要的陷阱.

There are basically two major pitfalls people stumble in with floating-point numbers.

  1. 规模问题.每个 FP 数字都有一个指数,它决定了数字的整体比例",因此您可以表示非常小的值或非常大的值,尽管您可以为此投入的位数是有限的.添加两个不同比例的数字有时会导致较小的数字被吃掉",因为无法将其放入较大的比例.

  1. The problem of scale. Each FP number has an exponent which determines the overall "scale" of the number so you can represent either really small values or really larges ones, though the number of digits you can devote for that is limited. Adding two numbers of different scale will sometimes result in the smaller one being "eaten" since there is no way to fit it into the larger scale.

PS> $a = 1; $b = 0.0000000000000000000000001
PS> Write-Host a=$a b=$b
a=1 b=1E-25
PS> $a + $b
1

作为这个案例的类比,您可以想象一个大型游泳池和一茶匙水.两者的尺寸都非常不同,但您可以单独轻松掌握它们的大致尺寸.然而,将茶匙倒入游泳池中,您仍然会看到一个装满水的游泳池.

As an analogy for this case you could picture a large swimming pool and a teaspoon of water. Both are of very different sizes, but individually you can easily grasp how much they roughly are. Pouring the teaspoon into the swimming pool, however, will leave you still with roughly a swimming pool full of water.

(如果学习这个的人对指数表示有问题,也可以使用值1100000000000000000000左右.)

(If the people learning this have trouble with exponential notation, one can also use the values 1 and 100000000000000000000 or so.)

然后就是二进制与十进制表示的问题.像 0.1 这样的数字不能用有限数量的二进制数字精确表示.不过,有些语言会掩盖这一点:

Then there is the problem of binary vs. decimal representation. A number like 0.1 can't be represented exactly with a limited amount of binary digits. Some languages mask this, though:

PS> "{0:N50}" -f 0.1
0.10000000000000000000000000000000000000000000000000

但是您可以通过重复将数字相加来放大"表示错误:

But you can "amplify" the representation error by repeatedly adding the numbers together:

PS> $sum = 0; for ($i = 0; $i -lt 100; $i++) { $sum += 0.1 }; $sum
9,99999999999998

不过,我想不出一个很好的类比来正确解释这一点.这基本上是相同的问题,为什么您只能用十进制近似表示 1/3 因为要获得确切的值,您需要在小数部分的末尾无限地重复 3.

I can't think of a nice analogy to properly explain this, though. It's basically the same problem why you can represent 1/3 only approximately in decimal because to get the exact value you need to repeat the 3 indefinitely at the end of the decimal fraction.

同样,二进制分数也适合表示一半、四分之一、八分之一等,但十分之一之类的东西会产生无限重复的二进制数字流.

Similarly, binary fractions are good for representing halves, quarters, eighths, etc. but things like a tenth will yield an infinitely repeating stream of binary digits.

还有另一个问题,尽管大多数人不会偶然发现这个问题,除非他们正在做大量的数字工作.但是,那些已经知道这个问题的人.由于许多浮点数只是精确值的近似值,这意味着对于实数 r 的给定近似值 f 可以有无限多个实数 r1, r2, ... 映射到完全相同的近似值.这些数字位于某个区间内.假设 rmin 是导致 fr<的 r 的最小可能值/em>max r 的最大可能值,它适用,然后你得到一个区间 [rmin, rmax] 其中该区间内的任何数字都可以是您的实际数字r.

Then there is another problem, though most people don't stumble into that, unless they're doing huge amounts of numerical stuff. But then, those already know about the problem. Since many floating-point numbers are merely approximations of the exact value this means that for a given approximation f of a real number r there can be infinitely many more real numbers r1, r2, ... which map to exactly the same approximation. Those numbers lie in a certain interval. Let's say that rmin is the minimum possible value of r that results in f and rmax the maximum possible value of r for which this holds, then you got an interval [rmin, rmax] where any number in that interval can be your actual number r.

现在,如果您对该数字执行计算(加法、减法、乘法等),则会失去精度.每个数字只是一个近似值,因此您实际上是在使用 intervals 执行计算.结果也是一个区间,并且近似误差只会变得更大,从而扩大了区间.您可能会从该计算中得到一个数字.但这只是可能结果区间中的一个数字,考虑到原始操作数的精度和计算导致的精度损失.

Now, if you perform calculations on that number—adding, subtracting, multiplying, etc.—you lose precision. Every number is just an approximation, therefore you're actually performing calculations with intervals. The result is an interval too and the approximation error only ever gets larger, thereby widening the interval. You may get back a single number from that calculation. But that's merely one number from the interval of possible results, taking into account precision of your original operands and the precision loss due to the calculation.

这种东西被称为 区间算术,至少对我来说它是我们的一部分大学的数学课程.

That sort of thing is called Interval arithmetic and at least for me it was part of our math course at the university.

这篇关于浮点数不准确示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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