2

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

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

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

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

4

4 回答 4

4

如果您不介意损失一点精度,您可以测试范围(请参阅Alfe 的回答):

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 个字节中,请明确测试这些。

于 2013-11-14T13:21:10.087 回答
1

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

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

范围是您的问题完全有意义的唯一方面。

如果涉及精度,您的问题就失去了意义,因为正如您所说,Python总是在内部使用双精度数,甚至一个简单3.3的 is,打包和解包为浮点数,仅在3.299999952316284之后:

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

所以实际上没有双精度可以表示为浮点数。(通常没有一个不是 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)
于 2013-11-14T13:34:17.860 回答
0

您可以通过将浮点数转换回双精度并将结果与​​ x 进行比较来检查双精度 x 是否可以精确地表示为浮点数。

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

于 2013-11-15T02:59:27.503 回答
-1

单精度

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

第一位是符号位 S,接下来的八位是指数位“E”,最后 23 位是小数“F”:


双精度

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

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

于 2013-11-14T13:26:07.227 回答