gpt4 book ai didi

c++ - 硬编码 double 的最低有效字节是一种好的舍入策略吗?

转载 作者:太空宇宙 更新时间:2023-11-04 14:47:00 24 4
gpt4 key购买 nike

我有一个函数进行一些数学计算并返回一个 double .由于 std::exp,它最终在 Windows 和 Android 下得到不同的结果。实现开始不同(Why do I get platform-specific result for std::exp?)。 e-17 舍入差异得到传播,最终它不仅仅是我得到的舍入差异(结果最终可以将 2.36 更改为 2.47)。当我将结果与一些预期值进行比较时,我希望此函数在所有平台上返回相同的结果。

所以我需要四舍五入我的结果。最简单的解决方案显然是(据我在网上找到的)做 std::ceil(d*std::pow<double>(10,precision))/std::pow<double>(10,precision) .但是,我觉得根据平台的不同,这仍然会导致不同的结果(而且,很难决定 precision 应该是什么)。

我想知道是否对 double 的最低有效字节进行硬编码可能是一个很好的舍入策略。

这个快速测试似乎表明"is":

#include <iostream>
#include <iomanip>

double roundByCast( double d )
{
double rounded = d;
unsigned char* temp = (unsigned char*) &rounded;
// changing least significant byte to be always the same
temp[0] = 128;
return rounded;
}

void showRoundInfo( double d, double rounded )
{
double diff = std::abs(d-rounded);
std::cout << "cast: " << d << " rounded to " << rounded << " (diff=" << diff << ")" << std::endl;
}

void roundIt( double d )
{
showRoundInfo( d, roundByCast(d) );
}

int main( int argc, char* argv[] )
{
roundIt( 7.87234042553191493141184764681 );
roundIt( 0.000000000000000000000184764681 );
roundIt( 78723404.2553191493141184764681 );
}

这个输出:

cast: 7.87234 rounded to 7.87234 (diff=2.66454e-14)
cast: 1.84765e-22 rounded to 1.84765e-22 (diff=9.87415e-37)
cast: 7.87234e+07 rounded to 7.87234e+07 (diff=4.47035e-07)

我的问题是:

  • unsigned char* temp = (unsigned char*) &rounded安全还是这里有未定义的行为,为什么?
  • 如果没有 UB(或者没有 UB 有更好的方法),这样的轮函数对于所有输入是否安全和准确?

注意:我知道 float 不准确。请不要标记为重复 Is floating point math broken?Why Are Floating Point Numbers Inaccurate? .我明白为什么结果不同,我只是在寻找一种方法让它们在所有目标平台上都相同。


编辑,我可能会重新表述我的问题,因为人们在问为什么我有不同的值(value)观以及为什么我希望它们相同。

假设您得到一个 double由于特定于平台的实现(如 std::exp ),计算结果可能会不同。如果你想修复那些不同的 double最终在所有平台上都具有完全相同的内存表示 (1),并且您想尽可能降低精度,那么修复最低有效字节是一种好方法吗? (因为我觉得四舍五入到任意给定的精度可能会丢失比这个技巧更多的信息)。

(1) “相同表示”是指如果将其转换为 std::bitset ,您希望看到所有平台的相同位序列。

最佳答案

不,四舍五入不是消除小错误或保证与错误执行的计算一致的策略。

对于将数字线分成范围的任何切片,您将成功地消除大多数微小的偏差(通过将它们放在同一个桶中并固定到相同的值),但是如果您的原始值对跨越边界。

在您对最低有效字节进行硬编码的特定情况下,非常接近的值

0x1.mmmmmmm100

0x1.mmmmmmm0ff

只有一个 ULP 的偏差...但在四舍五入后,它们相差 256 ULP。糟糕!

关于c++ - 硬编码 double 的最低有效字节是一种好的舍入策略吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54256429/

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