【LeetCode刷题记录】34.二进制数转字符串

174 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

题目来源:LeetCode-二进制数转字符串

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

示例1:

输入:0.625

输出:"0.101"

示例2:

输入:0.1

输出:"ERROR"

提示:0.1无法被二进制准确表示

提示:

32位包括输出中的"0."这两位。

二、思路分析:

因为该数num在0-1.0之间,因此可以采用折半比较法

与s(初始值0.5(二进制是0.1))进行比较

1.如果num比较小,则直接在小数点后面添加0,然后再让它与0.25(s/2,二进制是0.01)进行比较;

2.如果num比较大,则小数点后的第一位则是1,更新num为num-s,此时num必定介于0-0.5之间,然后更新s为0.25。

重复以上操作。

三、AC 代码:

    class Solution {
        public String printBin(double num) {
            if (num > 1 || num < 0) {
                return "ERROR";
            }
            StringBuffer stringBuffer = new StringBuffer();
            double tempVar = 0.50;
            stringBuffer.append("0.");
            while (num > 0) {
                if (stringBuffer.length() > 32) {
                    return "ERROR";
                }
                if (num < tempVar) {
                    stringBuffer.append("0");
                } else {
                    num = num - tempVar;
                    stringBuffer.append("1");
                }
                tempVar /= 2;
            }
            return stringBuffer.toString();
        }
    }

代码演进:

    class Solution {
        public String printBin(double num) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append('0');
            stringBuilder.append('.');
            for (int i = 0; i < 30; i++) {
                if (num == 0) return stringBuilder.toString();
                num *= 2;
                if (num >= 1) {
                    stringBuilder.append('1');
                    num -= 1;
                } else if (num > 0 && num < 1) {
                    stringBuilder.append('0');
                }
            }
            return "ERROR";
        }
    }

四、总结:

这道题有一个哲学问题,要处理的输入到底是什么?

如果处理string,那么就会有人说“0.2868311060592532”不能进行二进制表示的问题

如果处理的double,那么所有的double,最多只会有小数点后52位小数,而且是绝对意义上的精确

即使你看到的某个十进制小数会产生52位以后的小数,只要它在30~52位之间没有小数,就理应通过