二进制/十六进制浮点数输入

6
为什么只允许在十进制中使用小数点?为什么以下代码会报语法错误?
0b1011101.1101

我正在输入的数字是否存在歧义?除了 93.8125,似乎没有其他可能代表该字符串的数字。

同样的问题也适用于其他进制:

0x5d.d

我可以通过一个相当直观的函数解决这个问题:
def base_float(number_string, base):
    n = number_string.split('.')
    number = int(n[0], base)
    if len(n) > 1 and len(n[1]):
        frac_part = float(int(n[1], base)) / base**len(n[1])
        if number < 0:
            frac_part = -frac_part
        number += frac_part
    return number

它给我提供了我所期望的表现:

>>> base_float('0b1011101.1101', 2)
93.8125

int 可以接受任意进制,但是不能包含小数点,而 float 可以包含小数点,但是只能使用十进制。为什么呢?


1
我猜没有人真正需要这个功能,所以也就没有实现它。二进制、八进制和十六进制在整数方面比较有用,而十六进制则不太常用。但我不知道具体的原因是什么。 - user2357112
2
请注意,在非十进制文字中允许小数部分可能会在一些罕见情况下破坏现有代码。目前,0b1.bit_length()是有效的代码;如果引入二进制浮点文字,则0b1.将成为浮点文字,而0b1.bit_length()将成为语法错误。 - user2357112
1
@user2357112 这些问题已经出现了。将 1..__class__(1).__class__1.__class__ 进行比较。 - Hyperboreus
1
@Hyperboreus:我知道这些情况。现在更改语言以允许非十进制浮点文字可能会破坏之前正常工作的代码。没有可行的代码依赖于1.__class__ - user2357112
2
这实际上是一个语言设计问题,用户2357112的评论很中肯:没有人想要或需要足够的功能来实现它,并让其他 Python 开发人员相信这个功能值得加入核心语言。请注意,一种方法可以从十六进制字符串转换:尝试 float.fromhex('123.456') - Mark Dickinson
显示剩余3条评论
2个回答

5

它们被称为“小数点”;)

你可以使用一种科学记数法*

>>> 0b10111011101 * 0b10**-4
93.8125
>>> 0x5dd * 0x10**-1
93.8125
>>> 938125 * 10**-4 # note power is number of "decimal" places to shift
93.8125

* 是的,我意识到这不是真正的科学计数法

编辑

出于好奇,我使用dis模块反汇编了一些简单语句的字节码,以查看它们是否在运行时计算

>>> import dis
>>> def f():
...     return 0x5dd * 0x10**-1
...
>>> dis.dis(f)
  2           0 LOAD_CONST               6 (93.8125)
              3 RETURN_VALUE

看起来,当使用这种方法时,您不应该遇到性能下降的问题。

编辑2

......除非您使用Python 2

>>> import dis
>>> def f():
...     return 0x5dd * 0x10**-1
...
>>> dis.dis(f)
  2           0 LOAD_CONST               1 (1501)
              3 LOAD_CONST               4 (0.0625)
              6 BINARY_MULTIPLY
              7 RETURN_VALUE

没问题,您能详细说明一下原因吗?我很感兴趣。 - Peter Gibson

1

正如评论中的人们所写的那样:这只是没有被认为是必要的。

它们可以非常有用,特别是当需要存储给定实体的精确值并再次保留它时,但这些情况很少发生。

如果我用 if number < 0: 替换 if int_part < 0:,则您的函数非常有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接