来源:力扣(LeetCode)
描述:
二进制数转字符串。给定一个介于0和1之间的实数(如0.72),类型为double,打印它的二进制表达式。如果该数字无法精确地用32位以内的二进制表示,则打印“ERROR”。
示例1:
输入:0.625
输出:"0.101"
示例2:
输入:0.1
输出:"ERROR"
提示:0.1无法被二进制准确表示
提示:
- 32位包括输出中的 “0.” 这两位。
- 题目保证输入用例的小数位数最多只有 6 位
方法:转换二进制数
介于 0 和 1 之间的实数的整数部分是 0,小数部分大于 0,因此其二进制表示的整数部分是 0,需要将小数部分转换成二进制表示。
以示例 1 为例,十进制数 0.625 可以写成 1 +
1
2
1
1 \over 2^1
211 +
1
2
3
1 \over 2^3
231,因此对应的二进制数是 0.101(2) ,二进制数中的左边的 1 为小数点后第一位,表示
1
2
1
1 \over 2^1
211,右边的 1 为小数点后第三位,表示
1
2
3
1 \over 2^3
231。
如果将十进制数 0.625 乘以 2,则得到 1.25,可以写成 1 2 1 1 \over 2^1 211 + 1 2 3 1 \over 2^3 231,因此对应的二进制数是 1.01(2) 。二进制数 0.101(2) 的两倍是 1.01(2) ,因此在二进制表示中,将一个数乘以 2 的效果是将小数点向右移动一位。
根据上述结论,将实数的十进制表示转换成二进制表示的方法是:每次将实数乘以 2,将此时的整数部分添加到二进制表示的末尾,然后将整数部分置为 0,重复上述操作,直到小数部分变成 0 或者小数部分出现循环时结束操作。当小数部分变成 0 时,得到二进制表示下的有限小数;当小数部分出现循环时,得到二进制表示下的无限循环小数。
由于这道题要求二进制表示的长度最多为 32 位,否则返回 “ERROR",因此不需要判断给定实数的二进制表示的结果是有限小数还是无限循环小数,而是在小数部分变成 0 或者二进制表示的长度超过 32 位时结束操作。当操作结束时,如果二进制表示的长度不超过 32 位则返回二进制表示,否则返回 “ERROR"。
代码:
class Solution {
public:
string printBin(double num) {
string res = "0.";
while (res.size() <= 32 && num != 0) {
num *= 2;
int digit = num;
res.push_back(digit + '0');
num -= digit;
}
return res.size() <= 32 ? res : "ERROR";
}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.8 MB, 在所有 C++ 提交中击败了75.12%的用户
复杂度分析
时间复杂度:O©,其中 C 是结果字符串的最大长度,C=32。最多计算
32 位,每一位的计算时间是 O(1)。
空间复杂度:O©,其中 C 是结果字符串的最大长度,C = 32。存储结果的字符串需要 O© 的时间。
author:LeetCode-Solution