Python 使用减少的尾数(有效)浮点值将x浮点舍入为y

Python 使用减少的尾数(有效)浮点值将x浮点舍入为y,python,math,floating-point,Python,Math,Floating Point,我想了解如何用一个缩减尾数1(即20,19)取整一个IEEE float32,例如23位。 需要用Python逐步解决问题。以下是仅使用基本Python和标准的math模块的答案 from math import frexp, ldexp def roundbits(fval, nbits): """Return the floating-point value `fval` rounded to `nbits` bits in the significand."""

我想了解如何用一个缩减尾数1(即20,19)取整一个IEEE float32,例如23位。
需要用Python逐步解决问题。

以下是仅使用基本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**n位
,将最高有效位移回小数点之后。最后,使用新的有效位和旧的指数生成一个浮点数,
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

这可能是一个有用的起点你想要这样的东西吗?1.00-->'1'1.20-->'1.2'1.23-->'1.23'1.234-->'1.23'1.2345-->'1.23'您想要纯Python的答案,还是可以使用
numpy
模块(第一条注释中链接中接受答案中使用的常用第三方模块)?您是否在考虑如何将有效位的24位减少为20位的情况下,谁来决定是向上还是向下?或者,在Python中给定一个浮点值,如何提取有效位,然后用修改后的值构造一个新的浮点值?或者简单地说,如何实现将有效位舍入到20位的功能?这些是不同的问题。第一个是关于指定函数。第二个是关于操纵Python实体。第三种方法可以通过Veltkamp-Dekker拆分来实现,而无需直接操作有效位。这是一个有趣的想法,但我想知道它是否真的总是符合作者的要求,即是否可以保证
步骤将完全删除所有不需要的位(例如,在尾数末尾不会留下其他垃圾)?@SergGr:我不确定这是否完全符合OP的要求,但这确实满足了简要的问题描述。
舍入
步骤保证会产生一个整数,因此不需要的位肯定会消失。我不确定OP希望舍入到更高的数量级(具有更大的指数),例如,如果只需要一个位,则将
pi
四舍五入到
4
,但这是最合理的做法。