要计算包含 x 的 |x|•10 -8内的点的区间 [a, b] ,请设置 a 和 b:
double t = fabs(x) * 1e-8;
double a = x-t;
double b = x+t;
这是近似值,因为舍入误差可能会使 a 或 b 稍微不准确。如果您希望区间绝对包含所有点,您可以使用比 略高的值1e-8
,或者您可以使用更高级的技术。
一些警告:
如果您使用区间作为测试的一部分来确定某个计算值是否“几乎等于”另一个值,那么确定区间必须有多大需要分析所使用的浮点运算和所涉及的值。浮点值可能会产生从零到无穷大的误差,具体取决于具体情况。不可能说明任何单一量的公差在所有情况下都有用,甚至在“典型”情况下也是如此。
确定间隔可能有多大需要确定您的应用程序可以接受哪些错误。接受不相等的值以允许计算错误意味着您的程序有时会接受真正不相等的相等值(如果计算准确,没有错误)。因此,在程序产生不可接受的结果之前,您需要弄清楚间隔可以有多大。
显然,如果间隔必须大于它可能的值,那么你的程序就坏了;这种间隔的使用是行不通的。在这种情况下,您必须重新设计浮点运算以减少错误或重新设计程序以避免这种情况。
使用浮点数的表示来读取或更改其值通常是一个坏主意。这样做需要仔细注意编译器或平台规范的细节。(特别是,看起来在测试中工作的代码,实际上可能在编译器不支持的意义上被破坏,并且如果使用不同版本的编译器或编译开关(例如用于调试和优化,已更改。)此外,访问浮点数表示的代码通常不可移植。(最值得注意的是,一些平台以“小端”顺序存储 double 的字节,而一些平台以“大端”顺序存储字节。还有其他可移植性问题。)即使正确编写代码以访问一个浮点数,
对于大至 10 -81e-8
的容差,用于计算区间可能就足够了。也就是说,您可以使用普通的浮点运算,而不必计算浮点数的 ULP 或访问其表示。但是,如果您确实想要计算 IEEE-754 浮点数的 ULP,则可以使用此答案中的代码来执行此操作,而无需访问其表示。该代码是为float
而不是编写的double
,但您可以更改FLT
为DBL
以更改它使用的常量。当然也改成float
。double