用减少的尾数(有效)浮点将x浮点数舍入到y

时间:2019-01-10 16:37:30

标签: python math floating-point

我想了解如何舍入一个具有23位且尾数为1(即20,19)的IEEE float32。 需要使用Python的逐步解决方案。

1 个答案:

答案 0 :(得分:1)

这是仅使用基本Python和标准math模块的答案。

from math import frexp, ldexp

def roundbits(fval, nbits):
    """Return the floating-point value `fval` rounded to `nbits` bits
    in the significand."""
    significand, exponent = frexp(fval)
    scale = 2.0 ** nbits
    newsignificand = round(significand * scale) / scale
    return ldexp(newsignificand, exponent)

这是解释。要在其浮点表示的有效位中将值四舍五入到nbits位,请首先获取该有效位,然后对其进行缩放,以便最高有效位紧跟在小数点之后,其他位紧随其后。这就是frexp函数的作用。接下来,将该有效位数乘以2**nbits,这会将我们想要的位数放入小数点之前,而将不需要的位数放入小数点之后。 (对于nbits的合理值,该比例值和乘法都将精确完成。)然后,将该值四舍五入到最接近的整数,从而删除不需要的位。然后将该值除以2**nbits,将最高有效位移回到小数点之后。最后,使用新的有效数字和旧的指数来生成一个浮点数,这就是ldexp函数的作用。

此例程保持简单,因此忽略了一些极端情况。如果所需位数为负数,零或大于Python可以在其浮点值中存储的位数怎么办? Python通常使用double类型,该类型使用64位表示整个浮点数,并使用有效位表示53位(显式存储52位),但这不能保证。我将把错误检查留给您。

如果您使用以下方法测试此例程

for n in range(1, 52):
    print(n, roundbits(pi, n))

使用pi(它是53位二进制数字),

11.00100100001111110110101010001000100001011010001100001000110100

结果是

1 4.0
2 3.0
3 3.0
4 3.25
5 3.125
6 3.125
7 3.15625
8 3.140625
9 3.140625
10 3.140625
11 3.140625
12 3.1416015625
13 3.1416015625
14 3.1416015625
15 3.1416015625
16 3.1416015625
17 3.1416015625
18 3.1415863037109375
19 3.1415939331054688
20 3.1415939331054688
21 3.141592025756836
22 3.1415929794311523
23 3.141592502593994
24 3.1415927410125732
25 3.1415926218032837
26 3.1415926814079285
27 3.141592651605606
28 3.141592651605606
29 3.141592651605606
30 3.1415926553308964
31 3.1415926534682512
32 3.1415926534682512
33 3.1415926534682512
34 3.141592653701082
35 3.1415926535846666
36 3.1415926535846666
37 3.1415926535846666
38 3.1415926535846666
39 3.1415926535919425
40 3.1415926535883045
41 3.1415926535901235
42 3.1415926535901235
43 3.1415926535896688
44 3.141592653589896
45 3.1415926535897825
46 3.1415926535897825
47 3.1415926535897825
48 3.1415926535897967
49 3.1415926535897967
50 3.141592653589793
51 3.141592653589793