舍入一个双,以避免后续求和中的四舍五入

时间:2014-01-31 16:07:12

标签: c floating-point double ieee-754

我该如何实现?

// round to the nearest double so that x + ref doesn't cause round off error
double round(double x, double ref) { }

那样

double x = ....;
double y = ....;

double x_new = round(x, y);
return x_new + y; // NO ROUND OFF! 

换句话说(y + x_new) - x_new严格等于y

2 个答案:

答案 0 :(得分:2)

我们假设xy都是正面的。

S为双精度和x + y

有两种情况:

  • 如果xy,则S - y完全符合Sterbenz的引理。因此,加法(S - y) + y是精确的(它精确地生成S,这是一个双精度数)。因此,您可以为S - y选择x_newy + x_new不仅精确,而且与S产生的结果相同y + x

  • 如果x> y,然后根据y有效位数中设置的位数,您可能会遇到问题。例如,如果设置了y的有效位数中的最后一位,那么在z的二分之后,binade中的数字y可以具有z + y的属性精确。


这个答案与that answer含糊不清。

答案 1 :(得分:0)

Python中可能直接转换为C

的可能解决方案
import math
from decimal import Decimal


def round2(x, ref):
    x_n, x_exp     = math.frexp(x)
    ref_n, ref_exp = math.frexp(ref)
    assert x_exp <= ref_exp
    diff_exp = ref_exp - x_exp

    factor = 2. ** (53 - diff_exp)

    x_new_as_int = int(round(x_n * factor))
    x_new_as_norm_float = float(x_new_as_int) / factor
    return math.ldexp(x_new_as_norm_float, x_exp)


x = 0.001
y = 1.0

assert (y + x) - x != y

x_new = round2(x, y)

assert (y + x_new) - x_new == y

print "x:", Decimal(x)
print "x_new:", Decimal(x_new)

print "relative difference:", (x_new/x - 1.)