比较NS-3 C ++中的两个double值时出现奇怪的数学错误

时间:2014-02-14 14:01:20

标签: c++ math ns-3

我正在使用NS-3(用c ++编写)来模拟网络环境。

我正在使用其flowmonitor类来记录来自无线链接的性能指标。

我收集的一件事是当前和之前的数据包延迟或“抖动”之间的时间差异。

为了得到这个,我将一个数据包延迟的时间值(转换为双变量)减去前一个值。

0.0159051 - 0.0158002 = 0.0001049

但是,过了一会儿,数学似乎很奇怪,例如:

0.0159003 - 0.0158007 = 9.95972e-05

当答案显然应为0.0000996

进一步详细说明,我最初使用diff函数来找出差异。

template <typename T1, typename T2>
double diff(const T1& lhs, const T2& rhs)
{
  std::cout << lhs << " - " << rhs << std::endl;
  return lhs - rhs;
}

但是因为我发现了错误,我尝试了直接减法,但我得到了同样的错误。

2 个答案:

答案 0 :(得分:6)

浮点格式使用尾数和指数的二进制表示,它不能精确地表达每个十进制(十进制)数字小数,并且它的精度是有限的,因此请务必检查双重格式是否可以精确地表示您的值。有关双格式here on wikipedia的更多信息。关于堆栈溢出的浮点精度还有更多问题,请检查this one以及与之相关的其他内容。

有一些后果:

  1. 您不能指望您能获得所需数字的精确值
  2. 你不能简单地比较数字的相等性,(1.0+2.0)==3.0可以起作用,但任何更复杂的分数计算都无法比较相等......
  3. 浮点数的精度是有限的,当你将多个数相加或相乘时,尤其是不同的指数,你会在计算中累积大的误差(见Kahan summation algorithm

答案 1 :(得分:3)

实数从+无穷大延伸到无穷大,数字之间的差距极小。这不可能代表有限存储中的所有实数。

为了解决这个问题,计算机存储了数字的大小(作为指数)和有效位数(尾数)。这类似于将数字写为1.043 X 10 ^ -5。

由于存储不准确,您将获得舍入错误,这些舍入错误有时可能很重要。它确实意味着您无法在计算机上有意义地比较两个实数。充其量你可以说他们比给定的容忍度更接近。

为了说明这一点,将1.000除以3然后乘以3,你应该返回到1.000但是从1.000 / 3 = 0.333到3位小数,如果结果为0.999,不要感到惊讶。 (计算机使用二进制文件(基数2),因此这可能会有所不同,但这一点仍然存在)