什么是浮点/舍入误差的简单示例?

时间:2008-10-30 07:12:10

标签: c++ floating-accuracy

使用浮点变量时,我听说过“错误”。现在我正在尝试解决这个难题,我想我得到了一些舍入/浮点错误。所以我最终要弄清楚浮点错误的基础知识。

什么是浮点/舍入误差的简单示例(最好是在C ++中)?

编辑:例如说我有一个成功概率为p的事件。我做了10次此事件(p没有变化,所有试验都是独立的)。两次成功试验的概率是多少?我把它编码为:

double p_2x_success = pow(1-p, (double)8) * pow(p, (double)2) * (double)choose(8, 2);

这是浮点错误的机会吗?

9 个答案:

答案 0 :(得分:28)

 for(double d = 0; d != 0.3; d += 0.1); // never terminates 

答案 1 :(得分:26)

图片胜过千言万语 - 尝试绘制等式f(k)
enter image  description here左,你会得到这样的XY图(X和Y是对数刻度)。
enter image description here
如果计算机可以表示没有舍入误差的32位浮点数,那么对于每个k,我们应该得到零。但是,由于浮点误差累积,误差会随着k值的增大而增加。

HTH!

答案 2 :(得分:11)

通常,浮点错误是指无法存储在IEEE浮点表示中的数字。

整数存储时最右边的位为1,左边的每个位都是(2,4,8,...)的两倍。很容易看出这可以存储任何大小为2 ^ n的整数,其中n是位数。

浮点数的尾数(小数部分)以类似的方式存储,但是从左向右移动,每个连续位是前一个值的一半。 (它实际上比这复杂一点,但它现在会做的。)

因此,像0.5(1/2)这样的数字很容易存储,但不是每个数字<1都可以通过添加1/2,1 / 4,1 / 8形式的固定数量的分数来创建, ...

一个非常简单的例子是0.1或1/10。这可以通过一个无限系列来完成(我真的无法解决这个问题),但每当计算机存储0.1时,它就不是存储的数字。

如果您可以访问Unix计算机,很容易看到:

Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1
0.10000000000000001
>>> 

你会非常小心使用浮点数和双打数进行相等测试,无论你使用何种语言。

(至于你的例子,0.2是另一个无法存储在IEEE二进制数中的讨厌数字,但只要你测试不等式,而不是等式,如p <= 0.2,那么你将是没关系。)

答案 3 :(得分:5)

一个让我回想起来的简单的C,

char *c = "90.1000";
double d = 0;
sscanf(c,"%f",&d);
printf("%0.4f",d);

>> 90.0999

这是一个将DMS中的角度转换为弧度的函数,在上述情况下没有。

答案 4 :(得分:3)

这是抓住我的一个。

 round(256.49999) == 256
roundf(256.49999) == 257

双打和漂浮..

答案 5 :(得分:2)

这是我想到的最简单的方法,它适用于多种语言,很简单:

0.2 + 0.1

这里有一些关于REPL的示例,但是应该以任何符合IEEE754的语言返回此结果。

Python

>>> 0.2 + 0.1
0.30000000000000004

科特琳

0.2 + 0.1
res0: kotlin.Double = 0.30000000000000004

斯卡拉

scala> 0.2 + 0.1
val res0: Double = 0.30000000000000004

Java

jshell> 0.2 + 0.1
$1 ==> 0.30000000000000004

Ruby

irb(main):001:0> 0.2 + 0.1
=> 0.30000000000000004

答案 6 :(得分:0)

我喜欢Python解释器中的这个:

Python 2.7.10 (default, Oct  6 2017, 22:29:07) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1+0.2
0.30000000000000004
>>>

答案 7 :(得分:0)

超级简单:

a = 10000000.1
b = 1/10
print(a - b == 10000000)
print ('a:{0:.20f}\nb:{1:.20f}'.format(a, b))

打印(取决于平台)类似:

False                                                                                                                                 
a:10000000.09999999962747097015                                                                                                       
b:0.10000000000000000555 

答案 8 :(得分:0)

我认为 Ruby 在 its documentation 中有一个很好的例子:

sum = 0
10_000.times do
  sum = sum + 0.0001
end
print sum #=> 0.9999999999999062