面试题 05.02. 二进制数转字符串

面试题 05.02. 二进制数转字符串

难度中等

二进制数转字符串。给定一个介于0和1之间的实数(如0.72),类型为double,打印它的二进制表达式。如果该数字无法精确地用32位以内的二进制表示,则打印“ERROR”。

示例1:

 输入:0.625
 输出:"0.101"

示例2:

 输入:0.1
 输出:"ERROR"
 提示:0.1无法被二进制准确表示

提示:

  • 32位包括输出中的 "0." 这两位。
  • 题目保证输入用例的小数位数最多只有 6 位

思路:一个很直观的想法就是一直做减法,如0.72,首先考虑0.5,则剩余0.32,接下来考虑0.18,依次类推,如果可以精确地用32位以内的二进制表示(即最小的位的权重为2^(-32)),即表示考虑32次小数二进制的减法,如果能减完,则可以精确表示,否则不行。

现在我们来考虑上述算法的优化问题,首先注意到题目条件输入用例的小数位数最多只有 6 位,其实也可以得到在这种条件下得到的二进制位最多也只有6位。

证明:我们可以将输入看成是如下式子(因为除2等价于二进制下右移1位)

\frac{a}{2^6}=\frac{b*2^{6-x}}{2^x*2^{6-x}}=\frac{b}{2^x}

此时我们可以知道b与2互质,即b是奇数。

我们回到十进制下考虑这个问题,我们设这个数可以表示为

\frac{c}{10^6}=\frac{c}{2^6*5^6}

上面两种表示均表示同一个数,因此有

\frac{b}{2^x}=\frac{c}{2^6*5^6} \\=>b=\frac{c}{2^{6-x}*5^6} \\=>b=\frac{c*2^{x-6}}{5^6}

由于我们前面已经约束过b与2互质,因此必须要满足x-6<=0,否则b就不满足与2互质了,即有x<=6

当然,还有一个更简单单的方法:

\\\frac{1}{2^6}=0.015625 \\\frac{1}{2^7}=0.0078125

可以看到,到第7个二进制小数后,精度已经扩展到小数点后第七位了,有冗余的第七位就更不可能精确表示六位小数了,而小数每次除2精度一定会往后扩展一位。

另外为了避免浮点精度误差的问题,我们在这里采用乘法计算小数二进制的方式,设初始值为num(0<num<1):

        1.num=num*2

        2.如果num>=1,则num=num-1,并上一位二进制1;否则上一位二进制0

这样做的理由其实就是二进制下,数扩大两倍等价于二进制位发生左移。

class Solution {
public:
    string printBin(double num) {
        string str = "";
        double esp = 1e-10;
        for(int count = 5; count >= 0 && num > 0; -- count){
            num = num * 2;
            if(num >= 1){
                num -= 1;
                str = str + '1';
            }else{
                str = str + '0';
            }
        }
        if(num - (int)num < esp){
            return "0." + str;
        }
        return "ERROR";
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值