浮动到二进制

时间:2011-01-29 19:34:51

标签: python binary floating-point

我正在尝试将浮点数转换为二进制表示;我该怎么做到这一点? 然而,我的目标不是限制在2米,所以我希望能够轻松扩展到任何基础(3,4,8)ecc。

到目前为止,我对整数有一个简单的实现:

import string

LETTER = '0123456789' + string.ascii_lowercase
def convert_int(num, base):
    if base == 1:
        print "WARNING! ASKING FOR BASE = 1"
        return '1' * num if num != 0 else '0'

    if base > 36: raise ValueError('base must be >= 1 and <= 36')

    num, rest = divmod(num, base)
    rest = [LETTER[rest]]
    while num >= base:
        num, r = divmod(num, base)
        rest.append(LETTER[r])
    rest.reverse()
    return (LETTER[num] if num else '') + ''.join(str(x) for x in rest)

任何帮助表示赞赏:)

编辑:

def convert_float(num, base, digits=None):
    num = float(num)
    if digits is None: digits = 6

    num = int(round(num * pow(base, digits)))
    num = convert_int(num, base)
    num = num[:-digits] + '.' + num[:digits]
    if num.startswith('.'): num = '0' + num
    return num

是吗?为什么我会这样做?

>>> convert_float(1289.2893, 16)
'509.5094a0'
>>> float.hex(1289.2983)
'0x1.42531758e2196p+10'

P.S。 How to convert float number to Binary?

我已经阅读了那个讨论,但我没有得到答案..我的意思是,它只适用于0.25,0.125?我不明白“必须按相反顺序”这句话......

6 个答案:

答案 0 :(得分:16)

对于浮点数,有内置方法hex()。

http://docs.python.org/library/stdtypes.html#float.hex

它为您提供给定数字的十六进制表示。从十六进制到二进制的翻译形式是微不足道的。

例如:

In [15]: float.hex(1.25)
Out[15]: '0x1.4000000000000p+0'

In [16]: float.hex(8.25)
Out[16]: '0x1.0800000000000p+3'

答案 1 :(得分:12)

接下来回答一下理论。

以下说明并未解释IEEE浮点数标准仅涉及浮点数表示的一般概念

每个浮点数表示为小数部分乘以指数乘以符号。此外,所谓的指数偏差,将在下面解释。

所以我们有

  1. 签名位
  2. 小数部分数字
  3. 指数部分数字
  4. 具有8位分数和8位指数的基数2的示例

    分数部分的比特告诉我们下面的序列中哪些加号(要添加的数字)将包含在所代表的数值中

    2 ^ -1 + 2 ^ -2 + 2 ^ -3 + 2 ^ -4 + 2 ^ -5 + 2 ^ -6 + 2 ^ -7 + 2 ^ -8

    因此,如果您在小数部分中说01101101,则会给出

    0 * 2 ^ -1 + 1 * 2 ^ -2 + 1 * 2 ^ -3 + 0 * 2 ^ -4 + 1 * 2 ^ -5 + 1 * 2 ^ -6 + 0 * 2 ^ - 7 + 1 * 2 ^ -8 = 0.42578125

    现在可以表示的非零数字介于两者之间 2 ** -8 = 0.00390625和1 - 2 ** - 8 = 0.99609375

    这里指数部分进来。指数允许我们通过将分数部分乘以指数来表示非常大的数字。因此,如果我们有一个8位指数,我们可以将得到的分数乘以0到2 ^ 255之间的数字。

    回到上面的例子,让我们的指数为11000011 = 195。

    我们有01101101的分数部分= 0.42578125和指数部分11000011 = 195.它给出了我们的数字0.42578125 * 2 ^ 195,这是非常大的数字。

    到目前为止,我们可以表示2 ^ -8 * 2 ^ 0和(1-2 ^ -8)* 2 ^ 255之间的非零数字。这允许非常大的数字但不是非常小的数字。为了能够代表小数,我们必须在指数中包含所谓的偏差。这是一个总是从指数中减去的数字,以便允许表示小数字。

    让我们偏向127.现在所有指数都减去127.所以可以表示的数字在2 ^ -8 * 2 ^(0 - 127)和(1-2 ^ -8)* 2 ^之间( 255 - 127 = 128)

    示例号现在是0.42578125 * 2 ^(195-127 = 68),这仍然很大。

    示例结束

    为了更好地理解这一点,尝试尝试不同的基数和大小的分数和指数部分。一开始不要尝试使用奇数基数,因为它只会使必要的事情复杂化。

    一旦掌握了这种表示的工作原理,你就应该能够编写代码来获得任何基数,分数/指数部分组合中任何数字的表示。

答案 2 :(得分:8)

如果要将float转换为十进制小数点后d位的字符串:

  1. 将数字乘以base**d
  2. 舍入到最接近的整数。
  3. 将整数转换为字符串。
  4. 在结尾前插入.个字符d数字。
  5. 例如,在基数12中用0.1 十进制十几个位置表示0.1,

    1. 0.1×12 4 = 2073.6
    2. 舍入到最接近的整数→2074
    3. 转换为字符串→124A
    4. 添加小数点→0.124A

答案 3 :(得分:1)

这与您想要的二进制表示形式不同,但这会将IEEE 754转换为它的符号,尾数和基数,可用于以相当简单的方式创建十六进制表示。请注意,尾数的“值”是1 + BINARY,其中BINARY是二进制表示 - 因此返回中为-1。

我写了这段代码并宣布它是公共领域。

    def disect_float(f):
      f = float(f); #fixes passing integers
      sign = 0x00; #positive
      exp = 0;
      mant = 0;
      if(f < 0): #make f positive, store the sign
        sign = '-'; #negative
        f = -f;
      #get the mantissa by itself
      while(f % 1 > 0): #exp is positive
        f*=2
        exp+=1
      #while(f % 1 > 0):
      tf = f/2;
      while(tf % 1 <= 0): #exp is negative
        exp-=1;
        f=tf;
        tf=f/2;
        if(exp < -1024): break;
      mant=int(f);
      return sign, mant-1, exp;

答案 4 :(得分:1)

我发现有一个技巧可以使用简单的字符串操作来完成。我觉得这种方法比遇到的其他方法更简单。

    echo '<div  class="name_form">
<input type="text" name="field1" id="diploma_name" value=" "  placeholder=" name "required="required">
<button name="submit" id="diploma_submit" value="submit"> Scrie-ți numele pentru a personaliza diploma!</button>
</div>
<div style="margin-top: 50px;" id="diploma_name_display">
</div>
<script>
jQuery(document).ready(function(){
jQuery("#diploma_submit").click(function() {

        var firstfield_value = jQuery("#diploma_name").val();

        jQuery("#diploma_name_display").html( "<strong>" + firstfield_value +"</strong>" );
c = navigator.userAgent.search("Firefox");
if (c > -1) {
       jQuery("#diploma_name_display").css("margin-top: 50px;");
    }
      // $.window.stop(); //don't mind this, I have added this to stop the page from refreshing so my boss thinks this actually work.
     } );
     });
</script>';

输出:

s = "1101.0101"
s1, s2 = s.split(".")
s1 = int(s1, 2)
s2 = int(s2, 2)/(2**len(s2))
x = s1+s2
print(x)

希望对某人有帮助。

答案 5 :(得分:0)

直接回答标题并使用使用64位IEE754的float.hex,可以编写这个方法:

def float_to_bin(x):
  if x == 0:
    return "0" * 64
  w, sign = (float.hex(x), 0) if x > 0 else (float.hex(x)[1:], 1)
  mantissa, exp = int(w[4:17], 16), int(w[18:])
  return "{}{:011b}{:052b}".format(sign, exp + 1023, mantissa)

float_to_bin(-0.001) # '1011111101010000000010110011111101011000011011100110110100101010'

但请注意,这不适用于NaN和Inf。