std :: cbrt的舍入错误?

时间:2013-01-14 01:10:43

标签: c++ c++11 standards-compliance rounding-error cmath

我想知道是否应该将以下内容报告为标准库的gcc实现中的错误。

对于所有无符号整数i,如果我们将int(std::sqrt(i))与整数的实际平方根进行比较,则转换始终会给出良好的结果。如果我们对std::cbrt做同样的事情,则情况并非如此:

// Problem of rounding of std::cbrt for i from 0 to 100 million
// i, exact cbrt(i), result of int(std::cbrt(i))
2197, 13, 12
17576, 26, 25
24389, 29, 28
140608, 52, 51
185193, 57, 56
195112, 58, 57
226981, 61, 60
1092727, 103, 102
1124864, 104, 103
1442897, 113, 112
1481544, 114, 113
1560896, 116, 115
1685159, 119, 118
1815848, 122, 121
8741816, 206, 205
8869743, 207, 206
8998912, 208, 207
9393931, 211, 210
9938375, 215, 214
11543176, 226, 225
11852352, 228, 227
12487168, 232, 231
12649337, 233, 232
13481272, 238, 237
13651919, 239, 238
14348907, 243, 242
14526784, 244, 243
14706125, 245, 244
69426531, 411, 410
69934528, 412, 411
70957944, 414, 413
71991296, 416, 415
72511713, 417, 416
73560059, 419, 418
74618461, 421, 420
75151448, 422, 421
79507000, 430, 429
88121125, 445, 444
89314623, 447, 446
91733851, 451, 450
92345408, 452, 451
92959677, 453, 452
94818816, 456, 455
99897344, 464, 463 

你认为应该报告为缺陷吗?

1 个答案:

答案 0 :(得分:2)

std::cbrt返回浮点类型(float,double等),但您将其转换为int。这种转换截断而不是舍入,例如0.9999变为0.虽然2197的立方根是一个整数似乎是合乎逻辑的,但由于浮点类型以二进制形式存储,因此并不总是可以完美地表示十进制数,并且这种不准确性很可能是在std::cbrt执行的计算期间传播。例如,std::cbrt(2197) == 12.99999(我的编译器不支持它,因此我无法检查实际值),然后通过将其转换为int,您将值截断为12。

要更正代码,请在将std::cbrt(i)转换为int之前对{{1}}的结果进行舍入。请参阅this question了解如何执行此操作。