Python的float
数据类型确实使用双精度(64位)。但是,对于我的具体实现(通过OSC传输带有类型标记的值),我想区分可以表示为(32位)单精度浮点数和(64位)双精度浮点数的值。
更确切地说,我想做这样的事情:
if isdouble(value):
binary=struct.pack('>d', value)
else:
binary=struct.pack('>f', value)
有没有可行的方法来实现这个目标?
答案 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”部分: