gpt4 book ai didi

c++ - 如何在 C++ 中删除 float 的最后有效数字/尾数位

转载 作者:太空狗 更新时间:2023-10-29 23:15:24 24 4
gpt4 key购买 nike

我想以有效的方式删除 C++ 中 float 的最后 2 或 3 位有效数字。为了更准确地表述问题——我想丢弃 float 表示中的最后几个尾数位。

一些背景:我可以使用不同的方式得到同一个 float 。例如,如果我在矩形的角上使用双线性插值,由于机器精度限制,结果在矩形不同点的最后几位数字会有所不同。这些偏差的绝对顺序取决于内插值的顺序。例如,如果 p[i]~1e10(i == 1..4,矩形角处的值),则由机器精度引起的插值误差为~1e-4(对于 8 字节 float )。如果 p[i]~1e-10 那么错误将是~1e-24。由于内插值用于计算一阶或二阶导数,因此我需要“消除”这些差异。一个想法是从最终结果中删除最后几位数字。以下是我的看法:

#include <iostream>     // std::cout
#include <limits> // std::numeric_limits
#include <math.h> // fabs

template<typename real>
real remove_digits(const real& value, const int num_digits)
{
//return value;
if (value == 0.) return 0;
const real corrector_power =
(std::numeric_limits<real>::digits10 - num_digits)
- round(log10(fabs(value)));

//the value is too close to the limits of the double minimum value
//to be corrected -- return 0 instead.
if (corrector_power > std::numeric_limits<real>::max_exponent10 -
num_digits - 1)
{
return 0.;
}
const real corrector = pow(10, corrector_power);
const real result =
(value > 0) ? floor(value * corrector + 0.5) / corrector :
ceil(value * corrector - 0.5) / corrector;
return result;
}//remove_digits

int main() {
// g++ (Debian 4.7.2-5) 4.7.2 --- Debian GNU/Linux 7.8 (wheezy) 64-bit
std::cout << remove_digits<float>(12345.1234, 1) << std::endl; // 12345.1
std::cout << remove_digits<float>(12345.1234, 2) << std::endl; // 12345
std::cout << remove_digits<float>(12345.1234, 3) << std::endl; // 12350
std::cout << std::numeric_limits<float>::digits10 << std::endl; // 6
}

它有效,但使用了 2 个昂贵的操作——log10 和 pow。有没有更聪明的方法来做到这一点?如上所示,为了实现我的目标,我不需要删除实际的十进制数字,而只需将 float 的尾数表示中的 3-4 位设置为 0。

最佳答案

“一些背景知识:我可以使用不同的方式得出相同的 float 。”

这不是问题。 x 附近的“本地”分辨率大约为 x-std::next_after(x,0.0),它在很宽的范围内在 x 中呈线性。 p[i] 变化 20 个数量级的问题无关紧要,因为相对误差随 p[i] 线性变化,这意味着它也会线性变化用第一个表达式。

更一般地说,如果你想比较ab是否足够相似,只要测试a/b是否大约1.00000000。 (当 b 恰好为零时,您会遇到更大的问题 - 没有有意义的方式来说明 1E-10 是否“几乎等于”0)

关于c++ - 如何在 C++ 中删除 float 的最后有效数字/尾数位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29411378/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com