python - 接近完美的单精度浮点数转换代码

本文探讨了浮点数的存储和转换,包括如何将十进制小数转换为二进制浮点数。通过整数部分的重复相除和小数部分的重复相乘来说明转换过程。讨论了Python中浮点数转换的细节,强调了避免浮点运算误差的重要性,并提到了IEEE 754单精度浮点数的转换方法。
摘要由CSDN通过智能技术生成

浮点数存储

十进制浮点数转换为二进制浮点数:整数部分重复相除,小数部分重复相乘
整数部分重复相除:除基取余,直到商为0,余数反转
小数部分重复相乘:乘基取整,直到小数为0或者达到指定精度位,整数顺序排列
匠心之作java基础强化之强转溢出&浮点数运算精讲

0.5
过程1:转换乘对应的二进制小数 0.1
过程2:转换成对应的指数形式 2**1 * 1.0

过程1分解,因为这里整数部分为0不用处理,相当于只需要了解怎么把十进制的.5变成二进制的.1,在人的思维中,这里的1就相当于2**-1,正好是0.5,但是这对计算机来说是没有意义的,计算机的运算器都是整数的运算,再观察,假设目标形态是x,0.5 * 2=1;x * 2=1,于是bin(0.1) is float(0.5),那么如何用0.5推导出0.1,* 2对二进制意味着是比特左移,而小数点左边,对于计算机来说,是不认识小数的,于是只能当作整数处理,那么小数点左边这个整数就是5,5 * 2=10,即0.5 * 2=1,所以没假设的整数结果大于10后,就把这个十位拿掉存放起来,例如5 * 2一次就得到一个十位的1,拿掉1后就是0,获取小数结束:.1
那么为了知道规律,设定数值:bin(.11)即2**-1+2**-2即0.5+0.25即0.75

这里整数部分就是两位了,把这两个数当作整数就是75,那么要获取有效的1只能是百位:
75 * 2=150,拿掉百位的1,存储起来,待处理整数为50,50 * 2=100,拿掉百位的1,待处理数归零,取值结束,连续的获取了两个1,即bin(.11)
第一次拿掉的1,他表示的是0.5,第二次拿掉的1表示的是0.25,对应.11,第二次产生的1是放在第一次产生的1的后面。

假设我们不拿掉1,是否会有影响,150*2=300,个位、十位归零,运算结束,得到百位以上的数是3,3可以直接可以用二进制的数11表示,貌似也行。
方法1对应方法2的逻辑上的缺点:
1、貌似每次都要把超位的1都拿下来,这一步可以省去吗?
2、需要存储拿下来的1

优点:
1、超位后,拿掉一个位,之后就能少算一个位,于是每发生一次,之后运算压力都会减小,尤其是如果给一个小数点后很长数值的情况
2、接上,我们要每次都要推测超位的长度,因为我们规定了浮点数的数据存储长度就是那么多,存储长度盛满后,后面可能有的小数就要省略。而如果把位拿下来存在个东西里面,就只需要记录东西里面的长度。其实这里我很不确定,例如我用Python来表示,我会用到这个那个函数,但是我不知道机器中,是否有超位的部分的对应二进制的长度的运算方法。其实推测下来,可能的情况是待处理的数据其实是字符串,因为长度不定,计算机底层可能还无法存放那么长的数据,所以可能会需要用软件分割处理,所以不是单纯的数值,而数值只是计算的中间产物,而之后存放的二进制1,也是字符串,即:待处理字符串 == > 转换成运算器能处理的长度 == > 运算 == > 得到超位 == > 存放至表示二进制的字符串中。

上面提到的是小数部分如何转化成二进制小数部分,那么整数部分,其实就可以用十进制转二进制的方法直接转化成二进制整数部分。

Python 十进制转二进制

但是当作一个模拟硬件工作的流程,整数的0~9以及个十百千又如何变成二进制保存和运算的呢。保存其实就是一串二进制的01的串而已,没有类型规定的话,就是RAW。
又要开始思考了,假设我们拿到一个功能,即二进制1000就直接对应8,再底层的功能我们不考虑。
那么64位的cpu,他一次运算的长度可以是1111…挺长的,那就短说,假设我们用的处理器是4004,一次运算长度是4bit,即1111,从左往右,1分别对应8、4、2、1,最大表示无符号十进制15,假设给出整数0~9的任意一个,例如8,他记住了bin(1000)是8,结果就直接出来了。例如7,他至少知道7比8小,比4大,所以7-4=3,同理3-2=1,于是0111,当然他也可能直接记住7是0111。那么给出16呢,超出15的界限,这才开始真正的思考而不是推测+思考。16是一个字符串,他符合整数的书写规则,而且我们也是要把他当作整数处理。底层库中并没有他的数据,但是运算器中有3/2=1…1;5/2=2…1;6/2=3;7/2=3…1;9/2=4…1的数据,16就是一个十位的1和一个个位的6,16/2=(10+6)/2=5+3=8,而8正好是1000,而十进制的/2运算就是二进制的位移运算,所以16的二进制形态就是10000,那么17呢,17/2=(10+7)/2=8…1,余号前面意味着仍有10000,但余数意味着之前有个1,那么就是10000+1=10001。貌似有了苗头,只需要定义一个10/2=5。
那么一个更大点更复杂的数,例如bin(111111),int(0b111111): 63。求63在4004下转成二进制形态的过程。
5/2=2…1 : 1 2/2=1…0 : 0 1/2=0…1 : 1 5:bin(101)

bin(1010):10 10/2=5…0 : 0 5 : 101 越开始的位,越是二进制的低位(右侧)

    s=str(i%2)+s
    i=i//2

>>>s '1010011000' ```缕一缕思路,只要整数/2,无论整除还是有余,得到的结果相对于二进制来说,都是上了一位。而余数就是当前位置二进制的单位。

在这里插入图片描述

无注释版:

import re

while 1:
    num = str(input("输入一个数,显示其浮点数在二进制中的存储,输入exit退出:"))
    if num=="exit":
        print("退出运算")
        break
    if num=="0":
        print("00000000000000000000000000000000")
        continue
    if num=="nan":
        print("01111111110000000000000000000000")
        continue
    if num=="inf":
        print("01111111100000000000000000000000")
        continue
    if num=="-inf":
        print("11111111100000000000000000000000")
        continue

    if ((not re.compile("[^0-9.\-+]+").findall(num)) \
            and re.compile("[0-9]+").findall(num) \
            and ((num.count("-") == 0 and num.count("+") == 0) \
                 or (num.count("+") == 0 and num.count("-") == 1 and num[0] == "-") \
                 or (num.count("-") == 0 and num.count("+") == 1 and num[0] == "+")) \
            and (num.count(".") == 0 or num.count(".") == 1)):

        if num[0]=="-":
            sign="1"
            num=num[1:]
        elif num[0]=="+":
            sign="0"
            num = num[1:]
        else:sign="0"

        if num.count("."):
            numi=num[0:num.find(".")]
            numm=num[num.find(".")+1:]
        else:
            numi = num
            numm = "0"

        if numi=="0" and numm=="0":
            print("00000000000000000000000000000000")
            continue

        numib=bin(int(numi if numi else "0"))[2:]

        if numm!="0":
            nummb=""
            top=10**len(numm)
            numm=int(numm)
            if numib != "0":
                lmb=(25-len(numib))
                while len(nummb)<lmb:
                    numm=numm*2
                    if numm>top:
                        nummb+="1"
                        numm-=top
                    elif numm==top:
                        nummb += "1"
                        break
                    else:nummb += "0"
            else:
                for i in range(126):
                    numm = numm * 2
                    if numm<top:nummb += "0"
                    elif numm>top:
                        nummb += "1"
                        numm -= top
                        for i in range(24):
                            numm = numm * 2
                            if numm > top:
                                nummb += "1"
                                numm -= top
                            elif numm == top:
                                nummb += "1"
                                break
                            else:
                                nummb += "0"
                        break
                    elif numm==top:
                        nummb += "1"
                        break
            if "1" not in nummb:
                print("数值过小,赋值为0\n00000000000000000000000000000000")
                continue
        else:nummb="0"

        numb=numib+"."+nummb

        nume=numb.find(".")-1 if numb.find("1")<numb.find(".") else -(numb.find("1")-1)
        print
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值