浮点数转二进制

2022-01-09 00:00:00 python floating-point binary

问题描述

我正在尝试将浮点数转换为二进制表示;我怎样才能做到这一点?但是,我的目标是不受 2m 的限制,因此我希望可以轻松扩展到任何基础 (3, 4, 8) ecc.

I'm trying to convert a floating point number to binary representation; how can I achieve this? My goal is, however, not to be limited by 2m so I'm hoping for something that could be easily extended to any base (3, 4, 8) ecc.

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

I've got a straightforward implementation so far for integers:

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

对吗?为什么我会出现这种行为?

is that right? why do i get this behaviour?

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

附言如何将浮点数转换为二进制?

我已经阅读了该讨论,但我没有得到答案.我的意思是,它仅适用于 0.25、0.125 吗?而且我不明白必须以相反的顺序"这句话......

I've read that discussion, but I don't get the answer.. I mean, does it work only for 0.25, 0.125? and I dont understand the phrase 'must be in reverse order'...


解决方案

下一个答案,有点理论.

Next answer with a bit of theory.

下面的解释并不解释 IEEE 浮点标准,只是关于浮点数表示的一般概念

每个浮点数都表示为小数部分乘以指数乘以符号.另外还有所谓的指数偏差,下面会解释.

Every float number is represented as a fractional part multiplied by an exponent multiplied by a sign. Additionally there is so called bias for exponent, which will be explained bellow.

所以我们有

  1. 符号位
  2. 小数部分数字
  3. 指数部分数字

带有 8 位小数和 8 位指数的以 2 为底的示例

小数部分的位告诉我们下面序列中的哪些加数(要添加的数字)将包含在表示的数字值中

Bits in fraction part tell us which summands (numbers to be added) from sequence below are to be included in represented number value

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

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

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

So if you have say 01101101 in fractional part it gives

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

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

Now non-zero numbers that are representable that way fall between 2 ** -8 = 0.00390625 and 1 - 2**-8 = 0.99609375

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

Here the exponent part comes in. Exponent allows us to represent very big numbers by multiplying the fraction part by exponent. So if we have an 8bit exponent we can multiply the resulting fraction by numbers between 0 and 2^255.

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

So going back to example above let's take exponent of 11000011 = 195.

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

We have fractional part of 01101101 = 0.42578125 and exponent part 11000011 = 195. It gives us the number 0.42578125 * 2^195, this is really big number.

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

So far we can represent non-zero numbers between 2^-8 * 2^0 and (1-2^-8) * 2^255. This allows for very big numbers but not for very small numbers. In order to be able to represent small numbers we have to include so called bias in our exponent. It is a number that will be always subtracted from exponent in order to allow for representation of small numbers.

假设偏差为 127.现在所有指数都减去 127.因此可以表示的数字介于 2^-8 * 2^(0 - 127) 和 (1-2^-8) * 2^(255 - 127 = 128)

Let's take a bias of 127. Now all exponents are subtracted 127. So numbers that can be represented are between 2^-8 * 2^(0 - 127) and (1-2^-8) * 2^(255 - 127 = 128)

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

Example number is now 0.42578125 * 2^(195-127 = 68) which is still pretty big.

示例结束

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

In order to understand this better try to experiment with different bases and sizes for fractional and exponential part. At beginning don't try with odd bases because it only complicates things necessary.

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

Once you grasp how this representation works you should be able to write code to obtain representation of any number in any base, fractional/exponential part combination.

相关文章