1

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

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

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

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

IE

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;
}

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

4

2 回答 2

6

浮点格式使用尾数和指数的二进制表示,它不能精确地表示每个十进制(十进制)数字分数,并且它的精度是有限的,所以一定要检查双精度格式是否可以精确地表示你的值。更多关于双格式在这里维基百科。关于堆栈溢出的浮点精度还有更多问题,请检查这个和其他相关的问题。

有一些后果:

  1. 你不能指望你会得到你想要的数字的精确值
  2. 你不能简单地比较数字是否相等,(1.0+2.0)==3.0可以工作,但是任何更复杂的分数计算都不能比较相等......
  3. 浮点数的精度是有限的,当你将许多数字相加或相乘时,尤其是不同的指数,你会在计算中累积很大的误差(见Kahan summation algorithm
于 2014-02-14T14:05:01.423 回答
3

实数从 + 无穷大扩展到 - 无穷大,数字之间的差距非常小。这不可能在有限存储中表示所有实数。

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

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

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

于 2014-02-14T14:17:45.590 回答