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位之间没有小数,就理应通过