浮点比较函数说明 [英] Floating point comparison functions explanation

查看:133
本文介绍了浮点比较函数说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人在乎细节(code。通过code)来解释一下这个是干什么的?我看了布鲁斯·道森的纸比较漂浮,发现<一href="http://stackoverflow.com/questions/3874627/floating-point-comparison-functions-for-c">converted C#$ C $它ç,但不太了解它。什么是 maxDeltaBits 和它的目的是什么?在道森的文章就指出,这也可以应用到,所以如果是这样的话,那么你会需要转换的的Int64 而不是 INT32

 公共静态INT FloatToInt32Bits(浮点六)
{
    返回BitConverter.ToInt32(BitConverter.GetBytes(b)中,0);
}

公共静态布尔AlmostEqual2sComplement
    (浮起,浮动B,诠释maxDeltaBits)
{
    INT是不是= FloatToInt32Bits(一);
    如果(AINT℃,)//为什么只有当它是小于0?
        是不是= Int32.MinValue  - 是不是; //这样做的目的是什么?

    INT宾特= FloatToInt32Bits(B);
    如果(BINT℃,)//为什么只有当它是小于0?
        宾特= Int32.MinValue  - 宾特; //这样做的目的是什么?

    INT intDiff = Math.Abs​​(是不是 - 宾特);
    返回intDiff&其中; =(1&其中;&所述; maxDeltaBits); //为什么(1&LT;&LT; maxDeltaBits)?
}
 

解决方案

这一切都没有在布鲁斯·道森的论文。一个浮点(或双为此事),具有有限的precision。这也意味着有一组所有花车可以重新present的数字。

有什么道森的方法呢,就是计算有多少步骤之外的那一套你可以接受的同等价值,而不是使用固定的可接受的误差值。一个这样的步骤中的相对误差将与一个因子(几乎)2,其中所述相对误差为尾数的高值和更大的尾数的低值变化。然而,对于一个固定的步数的相对误差将不会发生变化不止于此。

要罗兰Illig公司:

为什么是一个事实,你不能直接测试两个FP号码平等?你可以,但你不会总是得到你所期望的。作为花车将工作存储不太大整数。然而,这可以写为一个十进制数字的有限数目的一小部分,一般不能用存储的二进制数字的数量有限。数量将被截断。如果你做一些运算,以截断引入的误差进场。此外,机器的FPU可以存储值具有较高的precision,你可以结束了价值不等precision的比较。

测试以下(C包括,更改为cstdio和CMATH现代C ++):

 的#include&LT; stdio.h中&GT;
#包括&LT;文件math.h&GT;

无效触发(浮X,浮动Y)
{
  如果(COS(x)的==余弦(y))为输出(余弦(%F)等于与cos(%F)\ñ,X,Y);
  其他的printf(COS(%F)不等于COS(%F)\ N,X,Y);
}

诠释的main()
{
  浮动F = 0.1;
  F = F * 0.1 * 0.1 * 0.1;
  如果(F == 0.0001f)的printf(%f等于0.0001 \ N,F);
  其他的printf(%F不等于0.0001 \ N,F);
  触发(1.44,1.44);
  返回0;
}
 

在我的机器上,我得到在这两种情况下的不等于分支:

  0.000100不等于0.0001
COS(1.440000)不等于COS(1.440000)
 

你会得到你的机器上什么是实现有关。

Anyone care to explain in detail (code by code) what this is doing? I have read Bruce Dawson's paper on comparing floats and have found converted C# code of it but don't quite understand it. What is maxDeltaBits and its purpose? In Dawson's paper it states that this can also be applied to double, so if that is the case then would you need to convert the double value to Int64 instead of int32?

public static int FloatToInt32Bits( float f )
{
    return BitConverter.ToInt32( BitConverter.GetBytes( b ), 0 );
}

public static bool AlmostEqual2sComplement
    ( float a, float b, int maxDeltaBits )
{
    int aInt = FloatToInt32Bits( a );
    if ( aInt < 0 ) // Why only if it is less than 0?
        aInt = Int32.MinValue - aInt; // What is the purpose of this?

    int bInt = FloatToInt32Bits( b );
    if ( bInt < 0 ) // Why only if it is less than 0?
        bInt = Int32.MinValue - bInt; // What is the purpose of this?

    int intDiff = Math.Abs( aInt - bInt );
    return intDiff <= ( 1 << maxDeltaBits ); // Why ( 1 << maxDeltaBits )?
}

解决方案

It's all there in Bruce Dawson's papers. A float (or double for that matter) has a finite precision. That also means there is a set of all the numbers that a float can represent.

What Dawson's method does, is to count how many steps away in that set you can accept as "equal value", rather than use a fixed acceptable error value. The relative error of one such step will vary with a factor (almost) 2, where the relative error is less for a high value of the mantissa and bigger for a low value of the mantissa. However, the relative error for a fixed number of steps will not vary more than that.

To Roland Illig:

Why is it "a fact that you can never test two FP numbers for equality directly"? You can, but you will not always get what you expect. Not too large integer numbers stored as floats will work. However, a fraction that can be written as a finite number of decimal digits, cannot generally be stored with a finite number of binary digits. The number will be truncated. If you do some arithmetic, the error introduced with the truncation comes into play. Also, the FPU of your machine may store values with a higher precision, and you can end up with a comparison of values with unequal precision.

Test the following (C includes, change to cstdio and cmath for modern C++):

#include <stdio.h>
#include <math.h>

void Trig(float x, float y)
{
  if (cos(x) == cos(y)) printf("cos(%f) equal to cos(%f)\n",x,y);
  else printf("cos(%f) not equal to cos(%f)\n",x,y);
}

int main()
{
  float f = 0.1;
  f = f * 0.1 * 0.1 * 0.1;
  if (f == 0.0001f) printf("%f equals 0.0001\n",f);
  else printf("%f does not equal 0.0001\n",f);
  Trig(1.44,1.44);
  return 0;
}

On my machine, I get the "not equal" branch in both cases:

0.000100 does not equal 0.0001
cos(1.440000) not equal to cos(1.440000)

What you get on your machine is implementation dependant.

这篇关于浮点比较函数说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆