【问题标题】:Can floor-ing a rounded number gives a different answer than the rounded number?对四舍五入的数字进行取舍可以给出与四舍五入不同的答案吗?
【发布时间】:2017-12-04 13:21:04
【问题描述】:

假设“round”返回双精度值,我是否更正了 floor(round($number)) 不一定等于 round($number)?

例如,假设 $number = 123456.9999999999999999。我猜“round”将是一个空操作,因为 $number 已经尽可能接近 123457。 然后“floor”将产生 123456。

这是正确的,还是有什么关于“地板”或“圆形”的东西可以防止这种情况发生?

【问题讨论】:

  • round 的结果绝不应该是非整数值。
  • "round" 在 C、PHP 和许多其他语言中返回双精度值。奥利弗,你是说对于非大整数,它们可以用双精度精确表示?
  • 我是说从来没有这样的情况:非整数值可以double表示,但最接近的整数值不能 被代表。

标签: floating-point rounding precision ieee-754 floor


【解决方案1】:

由于 IEEE-754 浮点表示的工作方式,1不可能表示非整数值(例如 123456.99999999999999999)和最接近的整数值(例如 123457)无法代表。

因此,在一个理智的实现中,round 的结果应该始终是一个整数值。事实上,对于 C 语言,语言标准要求这样做。2

因此,在这种理智的语言中,floor(round(x))round(x) 总是相同的。


1。 IEEE-754 现在非常普遍。从技术上讲,有可能构建一个浮点系统,而这不是正确的,但我怀疑这样的系统在实践中是否存在。

2。你的另一个例子,PHP,有一个sketchy "decimal precision" feature,这让我怀疑同样的保证是否适用!事实上,implementation 涉及各种疯狂的东西,包括转换为字符串并返回

【讨论】:

  • 我对“不可能”提出质疑:没有理由不能创建一种浮点格式,其中并非所有小整数都可以精确表示。它只是不是一种特别好的格式,并且与我见过的任何现有的现实世界格式都不匹配。
  • @MarkDickinson - 可能是真的。虽然这个问题被标记为“ieee-754”,所以我在这个上下文中回答。不过,我会更新我的答案以明确表示:)
  • 啊,对不起。我错过了那个标签。完全同意 IEEE 754 格式是不可能的。
【解决方案2】:

对一个四舍五入的数字求取与四舍五入后的数字不同的答案吗?

有时查看角落案例可以揭示反例。

void rtest(double x) {
  double y1 = floor(round(x));
  double y2 = round(x);
  printf("%d %- 14e %- 14e %- 14e\n", y1 != y2, x, y1, y2);
}

int main(void) {
  double x[] = { 0.0, DBL_TRUE_MIN, DBL_MIN, 1.0, 3.14, 3.99, DBL_MAX, 1.0/0.0, 0.0/0.0};
  for (unsigned i=0; i< sizeof x/sizeof x[0]; i++) {
    rtest(x[i]);
    rtest(-x[i]);
  }
}

输出

0  0.000000e+00   0.000000e+00   0.000000e+00 
0 -0.000000e+00  -0.000000e+00  -0.000000e+00 
0  4.940656e-324  0.000000e+00   0.000000e+00 
0 -4.940656e-324 -0.000000e+00  -0.000000e+00 
0  2.225074e-308  0.000000e+00   0.000000e+00 
0 -2.225074e-308 -0.000000e+00  -0.000000e+00 
0  1.000000e+00   1.000000e+00   1.000000e+00 
0 -1.000000e+00  -1.000000e+00  -1.000000e+00 
0  3.140000e+00   3.000000e+00   3.000000e+00 
0 -3.140000e+00  -3.000000e+00  -3.000000e+00 
0  3.990000e+00   4.000000e+00   4.000000e+00 
0 -3.990000e+00  -4.000000e+00  -4.000000e+00 
0  1.797693e+308  1.797693e+308  1.797693e+308
0 -1.797693e+308 -1.797693e+308 -1.797693e+308
0  inf            inf            inf          
0 -inf           -inf           -inf          
1 -nan           -nan           -nan          
1  nan            nan            nan

在处理 ieee-754 数字时,floor(round(x)) != round(x) 为真或(根据 OP 的问题“不一定相等”)当 x 不是非数字时。

否则round() 的结果始终是整数值或无穷大,并且`floor-ing 不会改变值。

我检查了各种舍入模式,结果都一样。

【讨论】:

    猜你喜欢
    • 2015-07-15
    • 2015-11-12
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 2023-01-12
    • 2012-08-04
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多