Search code examples
pythonfloating-pointdouble-precision

Differentiate between single and double precision


Python's float data type really uses double precision (64bit). However, for my specific implementation (that transmits typetagged values via OSC) I would to like differentiate between values that can be represented as (32bit) single precision floats and (64bit) double precision floats.

More precisely, I'd like to do something like this:

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

Is there any feasible way to achieve this?


Solution

  • I propose to just try it using float and if that fails (due to range overflow) use the double version:

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

    The range is the only aspect in which your question makes perfect sense.

    If it comes to precision, your question loses to make sense because, as you say, Python always uses doubles internally, and even a simple 3.3 is, packed and unpacked as float, only 3.299999952316284 afterwards:

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

    So virtually no double can be represented as a float. (Typically none that isn't an int or otherwise coming out of a float originally.)

    You could, however, make a check whether the packed-unpacked version of your number equals the original, and if it does, use the float version:

    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)