区分单精度和双精度

时间:2013-11-14 13:17:45

标签: python floating-point double-precision

Python的float数据类型确实使用双精度(64位)。但是,对于我的具体实现(通过OSC传输带有类型标记的值),我想区分可以表示为(32位)单精度浮点数和(64位)双精度浮点数的值。

更确切地说,我想做这样的事情:

 if isdouble(value):
    binary=struct.pack('>d', value)
 else:
    binary=struct.pack('>f', value)

有没有可行的方法来实现这个目标?

4 个答案:

答案 0 :(得分:4)

你可以测试范围,如果你不介意失去一点精度(见Alfe's answer):

def isdouble(value):
    return not (1.18e-38 <= abs(value) <= 3.4e38)

或反转以测试单精度:

def issingle(value):
    return 1.18e-38 <= abs(value) <= 3.4e38:

这会阻止引发OverflowError例外,另一种方法是抓住它。

请注意,float('-0')float('+0')float('inf')float('-inf')float('nan')会在这些测试中测试为双倍;如果你希望这些存储在4个字节而不是8个字节中,请明确地测试它们。

答案 1 :(得分:1)

我建议使用float尝试它,如果失败(由于范围溢出)使用双版本:

try:
  binary = struct.pack('>f', value)
except OverflowError:
  binary = struct.pack('>d', value)

范围是您的问题非常有意义的唯一方面。

如果涉及到精确性,那么你的问题就失去了意义,因为正如你所说,Python 总是在内部使用双精度,甚至一个简单的3.3也是,包装和解包为浮点数,之后只有3.299999952316284

struct.unpack('>f', struct.pack('>f', 3.3))
(3.299999952316284,)

所以几乎没有 double可以表示为float。 (通常没有一个不是int或者最初从浮动中出来的。)

但是,您可以检查您的号码的打包解包版本是否等于原始版本,如果是,请使用浮动版本:

try:
  binary = struct.pack('>f', value)
  if struct.unpack('>f', binary)[0] != value:
    binary = struct.pack('>d', value)
except OverflowError:
  binary = struct.pack('>d', value)

答案 2 :(得分:0)

您可以通过将float转换为double并将结果与​​x进行比较来检查double x是否可以完全表示为float。

所有浮点数都可以精确表示为double,因此反向转换不涉及舍入。当且仅当float等于该double时,结果将等于原始double。

答案 3 :(得分:-1)

单精度

IEEE单精度浮点标准表示需要32位字,可以表示为从0到31编号,从左到右。

第一位是符号位S, 接下来的8位是指数位,'E'和 最后的23位是“F”部分:


双精度

IEEE双精度浮点标准表示需要64位字,可以表示为从0到63编号,从左到右。

第一位是符号位S, 接下来的11位是指数位,'E'和 最后的52位是“F”部分: