exp10 different to pow(10)
exp10 different to pow(10)
首先,我意识到大多数以10为基数的数字不能精确地以2为基数表示,所以我的问题并不是关于浮点算术的缺陷。
我正试图写一个函数,该函数将尝试通过检查最后6个有意义的数字是否在一定范围内,并将其更改为下一个可表示的一些假定的精确值(仅用于显示目的-除非它是整数或2的幂)来纠正被累积舍入误差污染的双精度。
我的函数的一个组件让我惊讶的是exp10的输出;据我所知,只要两个双精度之间的间距小于2,那么存储为双精度的整数值应该是精确的-尽管10^14正在推动它,这应该是一个精确的整数(因为10^14 =~ 2^46.507 <2 ^ 53)。然而,这不是我的测试显示。
我调试工作的摘录(没有什么明显的)和输出如下:
double test = 0.000699;
double tmp = fabs(test);
double exp = 10.0 - floor(log10(tmp));
double powTen = exp10(10.0 - floor(log10(tmp)));
double powTen2 = exp10(exp);
double powTen3 = exp10((int)exp);
double powTen4 = exp10(exp);
double powTen5 = pow(10, exp);
printf("exp: %.16lfn", exp);
printf("powTen: %.16lfn", powTen);
printf("powTen2: %.16lfn", powTen2);
printf("powTen3: %.16lfn", powTen3);
printf("powTen4: %.16lfn", powTen4);
//these two are exact
printf("10^14: %.16lfn", exp10(14));
printf("powTen5: %.16lfn", powTen5);
printf("exp == 14.0: %dn", exp == 14.0);
输出:exp: 14.0000000000000000
powTen: 100000000000000.1250000000000000
powTen2: 100000000000000.1250000000000000
powTen3: 100000000000000.1250000000000000
powTen4: 100000000000000.1250000000000000
10^14: 100000000000000.0000000000000000
powTen5: 100000000000000.0000000000000000
exp == 14.0: 1
pow得到确切的答案,exp10与硬编码的int一样。对于所有其他情况,我加1/8(10^14和10^14 +下一个可表示的间隔是1/64)。文档中说exp10应该等于pow。有人能看出我漏掉了什么吗?
编辑-与O3, O2, O1优化我得到预期的输出- 除非数据不能知道,直到运行时。此时,exp10仍然不正常
很可能您的exp10
实现行为不正常。请注意,它返回的结果有时会偏离一个ulp(相对于您的10^14,这是0.125)
这是一个相当可恶的错误;你有一个情况,正确的答案是可以表示为double
,但exp10
不这样做。
我赞同Ben Voigt的评论,编译器有时可能自己求值,而不是把它们传递给数学库。它可能做得更好,因为它可能链接到任意精度的数学库。您可以尝试-fno-builtin
选项,看看它是否改变了什么。
不幸的是,我认为clibm没有实现exp10
。否则,我建议你使用它,不要担心。
EDIT:我所拥有的eglibc
源的副本似乎实现了exp10
:
double
__ieee754_exp10 (double arg)
{
/* This is a very stupid and inprecise implementation. It'll get
replaced sometime (soon?). */
return __ieee754_exp (M_LN10 * arg);
}
- 在C++中如何在没有pow的情况下进行基础计算
- 理解GCC中的std::pow实现
- 子例程,不使用 pow,并带有参数和返回
- 整数溢出,最大值为 pow(10,19)
- 在 while 循环中使用 pow() 函数 C++
- different between int **arr =new int [ n]; and int a[i][j]?
- 在C++不使用 POW 的情况下处理负指数
- C++ 中 pow() 函数的输出没有给出准确的答案
- 没有匹配'pow'功能
- 为什么 while ((i <= 9) && square == pow(i, 2)) { cou
- Arduino Pow() 和 Armstrong 数问题
- C++在不使用pow或循环的情况下计算一个数字的幂
- 让constexpr在OSX上的C++17中使用pow
- Why (int)pow(2, 32) == -2147483648
- 错误:"int pow(double,int)"与上一个声明int pov(double a,int
- Pow 在 C++ 中无法按预期工作
- C++使用负矢量大小计算的 pow 行为
- Rcpp 'candidate function has different number of parameters (expected 0 but has 1)'
- 在C++中使用 pow() 时出错
- exp10 different to pow(10)