gpt4 book ai didi

c++ - 如何检查 float 的依赖关系

转载 作者:IT老高 更新时间:2023-10-28 23:03:15 26 4
gpt4 key购买 nike

我想确定(在 C++ 中)一个 float 是否是另一个 float 的乘法逆数。问题是我必须使用第三个变量来做到这一点。例如这段代码:

float x=5,y=0.2;
if(x==(1/y)) cout<<"They are the multiplicative inverse of eachother"<<endl;
else cout<<"They are NOT the multiplicative inverse of eachother"<<endl;

将输出:“他们不是……”这是错误的,这段代码:

float x=5,y=0.2,z;
z=1/y;
if(x==z) cout<<"They are the multiplicative inverse of eachother"<<endl;
else cout<<"They are NOT the multiplicative inverse of eachother"<<endl;

会输出:“他们是……”这是对的。
为什么会这样?

最佳答案

浮点精度问题

    这里有两个问题,但都来自同一个根

您无法精确比较 float 。您不能精确地减去或除以它们。你不能精确地为他们计算任何东西。对它们进行的任何操作都可能(并且几乎总是会)给结果带来一些错误。偶a=0.2f不是一个精确的操作。此处其他答案的作者很好地解释了其更深层次的原因。 (我对此表示感谢并投票给他们。)

这是您的第一个也是更简单的错误。你不应该,neverneverneverNEVER在他们身上使用= = 或任何语言的等价物。

而不是 a==b , 使用 Abs(a-b)<HighestPossibleError而是。


    但这不是您任务中的唯一问题。

Abs(1/y-x)<HighestPossibleError也不行。至少,它不会经常工作。为什么?

让我们取 x=1000 和 y=0.001 对。让我们将 y 的“起始”相对误差设为 10-6

(相对误差 = 误差/值)。

值的相对误差在乘法和除法时增加。

1/y 约为 1000。它的相对误差是相同的 10-6。 (“1”没有错误)

这使得绝对误差 =1000*10-6=0.001。当您稍后减去 x 时,将只剩下该错误。 (绝对误差在加法和减法中相加,x 的误差可以忽略不计。)当然,你不会指望这么大的误差,HighestPossibleError 肯定会设置得更低,你的程序会抛出一对好的 x,是的

因此,浮点运算的下两个规则:尽量不要将较大的估值器除以较小的估值器,上帝保佑你不要在那之后减去接近的值。

有两种简单的方法可以避免这个问题。

  • 通过求 x,y 的绝对值较大,然后将 1 除以较大的值,然后再减去较小的值。

  • 如果要比较1/y against x ,当您使用字母而不是值时,并且您的操作不会出错,将比较的两边乘以 y你有1 against x*y . (通常你应该检查那个操作中的符号,但是这里我们使用abs值,所以它是干净的。) 结果比较根本没有除法。

简而言之:

1/y V x   <=>   y*(1/y) V x*y   <=>   1 V x*y 

我们已经知道 1 against x*y 这样的比较应该这样做:

const float HighestPossibleError=1e-10;
if(Abs(x*y-1.0)<HighestPossibleError){...

就是这样。


附:如果你真的需要all一行,请使用:

if(Abs(x*y-1.0)<1e-10){...

但这是一种糟糕的风格。我不建议这样做。

附言在您的第二个示例中,编译器会优化代码,以便在运行任何代码之前将 z 设置为 5。因此,即使是 float ,检查 5 对 5 也有效。

关于c++ - 如何检查 float 的依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9136860/

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