2017-01-27 3 views
1

へ:https://www.h-schmidt.net/FloatConverter/IEEE754.htmlPythonのフロートこのwebisteに見られるように32ビットの数が限られ

私は、スタックオーバーフローの5かそこらの記事に目を通してきたが、彼らは私が探していますどのような非常にではありません。例:

import struct 

getBin = lambda x: x > 0 and str(bin(x))[2:] or "-" + str(bin(x))[3:] 

def floatToBinary64(value): 
    val = struct.unpack('Q', struct.pack('d', value))[0] 
    return getBin(val) 

def binaryToFloat(value): 
    hx = hex(int(value, 2)) 
    return struct.unpack("d", struct.pack("q", int(hx, 16)))[0] 

# floats are represented by IEEE 754 floating-point format which are 
# 64 bits long (not 32 bits) 

# float to binary 
binstr = floatToBinary64(NUMBER) 
print('Binary equivalent of .1:') 
print(binstr + '\n') 

# binary to float 
fl = binaryToFloat(binstr) 
print('Decimal equivalent of ' + binstr) 
print(fl) 

これは私が探しているものにかなり近いことがわかります。あなたがnumberがこのコードに.1を入れると、それは.1としてそれを列挙しますが、ウェブサイトには私には0.10000000149011612が与えられます。

誰でも助けてもらえると嬉しいです!

+0

どのウェブサイトから回答が得られますか?編集:申し訳ありませんが、トップに... duh – BretD

+0

なぜタイトルは32と言うのですか? –

+0

私はまだ質問について混乱しています...だから、ウェブサイトは32ビットの浮動小数点数で、Pythonは64ビットの浮動小数点数を使用しています。なぜ値が異なるのか混乱していますか? – BretD

答えて

2

これは、Pythonがあなたにその番号の最も良い表現を示しているからです。値は、実際に、まさにこのです:

リテラル 0.1が変身まさにある
>>> '%.60f' % fl 
'0.100000000000000005551115123125782702118158340454101562500000' 

>>> '%.60f' % 0.1 
'0.100000000000000005551115123125782702118158340454101562500000' 

(ああ、それはあることそれが32ではなく64ビットで行われているため0.10000000149011612ではありませんし、実際に。 1つは0.100000001490116119384765625である必要があります。そのコンバータページは不正確です)

+0

ああ、それは理にかなっている!しかし、ウェブサイトの.1は0.10000000149011612ではありませんが、0.10000000000000000555という理由はありますか? –

+0

@AndersonP最後の私のコメントや上記のBretDのコメントを見てください。 –

+0

Pythonで32ビットをシミュレートする方法はありますか、または64ビットしか使用できませんか?あなたの助けをありがとう –

1

gmpy2ライブラリを使用すると、標準の32ビットおよび64ビットIEEEマット。ここ

は一例であり:

>>> import gmpy2 
>>> gmpy2.set_context(gmpy2.ieee(64)) 
>>> gmpy2.mpfr("0.1").__format__(".60f") 
'0.100000000000000005551115123125782702118158340454101562500000' 
>>> gmpy2.set_context(gmpy2.ieee(32)) 
>>> gmpy2.mpfr("0.1").__format__(".60f") 
'0.100000001490116119384765625000000000000000000000000000000000' 

編集:追加例機能32ビットIEEEフォーマットにMPFRを変換します。

import gmpy2 
gmpy2.set_context(gmpy2.ieee(32)) 

def mpfr_to_float(x): 
    '''Convert an mpfr object created by the IEEE 32-bit compatible 
    context to a 32 character string containing 0 and 1.''' 

    # Check for special values first. 

    if gmpy2.is_infinite(x): 
     if gmpy2.is_signed(x): 
      return "1" * 9 + "0" * 23 
     else: 
      return "0" + "1" * 8 + "0" * 23 

    if gmpy2.is_nan(x): 
     return "0" + "1" * 31 

    if gmpy2.is_zero(x): 
     if gmpy2.is_signed(x): 
      return "1" + "0" * 31 
     else: 
      return "0" * 32 

    # Extract the mantissa, exponent, and precision. Note that the 
    # values are slightly different than the IEEE 32-bit standard. 

    mnt, exp, prc = x.digits(2) 

    # MPFR explicitely stores the leading bit of the mantissa so the 
    # precision is 24. To support subnormals, MPFR also uses a more 
    # negative minimum exponent and decreases the precision of the 
    # mantissa but maintains the leading '1' bit. 

    # Remove any leading sign bit from the mantissa string. 
    if mnt[0] == "-": 
     sign_char = "1" 
     mnt = mnt[1:] 
    else: 
     sign_char = "0" 

    # Check for subnormals 
    if exp + 126 <= 0: 
     # Drop the last bit since it will always be '0' and after the 
     # adjustments for subnormals, the leading bit will be '0'. 
     mnt = mnt[:-1] 
    else: 
     # Drop the leading '1' bit for normal numbers. 
     mnt = mnt[1:] 

    # Handle subnormals by shifting trailing bits from the mantissa 
    # string to the beginning. Adjust the exponent to match. 
    while exp + 126 < 0: 
     mnt = mnt[-1] + mnt[:-1] 
     exp = exp + 1 

    # Adjust the exponent to account for removing a bit from the 
    # mantissa string. 
    exp = exp - 1 

    # Add 127 to the exponent to account for the IEEE encoding. 
    exp = exp + 127 

    # Validate exponent range. 
    if (exp > 255) or (exp < 0): 
     raise ValueError("exp is out of bounds") 

    # Build and return the binary string. 
    result = sign_char + format(exp, "08b") + mnt 
    if len(result) != 32: 
     raise ValueError("something is wrong....") 

    return result 


if __name__ == "__main__": 
    print(mpfr_to_float(gmpy2.mpfr("0.1"))) 

免責事項#1:これは本当に@Stefan Pochmannの答えにコメントする必要がありますが、私はコード例が参考になると思いました。

免責事項#2:gmpy2を維持しています。

+0

私たち自身で 'struct.pack' /' struct.unpack'を使って表現するよりも、あまり意味がありませんが、使用するにはもっと単純でより良い/もっと安全です。そして私の 'ctypes.c_float(0.1).value'ハックより優れています。ちょうど1つの質問:gmpy2はIEEE表現のビットを表示していますか(そのWebページとOPのコードで行われています)? –

+0

@StefanPochmann残念ながら。基礎となるMPFRライブラリーは、異なる内部表現を使用します。 MPFRはIEEEのfloatとdoubleの値に変換する関数を提供していますが、Pythonはネイティブの32ビット浮動小数点型を提供していないので、floatのバージョンは公開しません。 Pythonのmpfr-to-floatコンバータを作成し、私の答えを編集しようとします。 – casevh

+0

@StefanPochmannサンプル関数が追加されました。 – casevh

関連する問題