1. 题目:
给定一个介于0和1之间的实数(如0.72),类型为double,打印它的二进制表达式。如果该数字无法精确地用32位以内的二进制表示,则打印“ERROR”。
2. 解题思路:
1)检查输入数字是否在0和1之间,否则返回错误
2)使用"0."作为二进制字符串的开头
3)重复以下步骤直到数字变为0或超过32位:
- 将数字乘以2
- 如果结果>=1,添加"1"到字符串,并减去1
- 否则,添加"0"到字符串
4)如果超过32位仍未归零,返回"ERROR"
3. 代码完整实现(C++):
#include <cmath>
#include <iostream>
#include <string>
using namespace std;
string doubleToBinaryString(double num) {
// 检查输入范围
if (num <= 0 || num >= 1) {
return "ERROR";
}
string binary = "0.";
int count = 0;
while (num > 0) {
if (count >= 32) {
return "ERROR";
}
/*
乘以2的作用是"查看当前位是0还是1":
1. 乘以2相当于把二进制数左移一位。
例如:0.101 × 2 = 1.01(小数点右移)
2. 整数部分就会告诉我们这一位是0还是1,
1.01的整数部分是1 → 这一位是1,
然后去掉整数部分继续处理小数部分。
3. 重复这个过程就能逐位得到二进制表示。
*/
num *= 2;
if (num >= 1) {
binary += "1";
num -= 1;
} else {
binary += "0";
}
count++;
}
return binary;
}
int main() {
double num = 0.72; // 0.625
string result = doubleToBinaryString(num);
cout << "二进制表示: " << result << endl;
return 0;
}
4. 代码分析:
为什么二进制转换要一直乘以2?下面用更简单的方式解释这个原理:
十进制和二进制小数对比
先看十进制小数(我们日常用的):
比如 0.625 表示:6/10 + 2/100 + 5/1000
每位权重是:1/10, 1/100, 1/1000…(即10的负幂次)
二进制小数类似:
比如 0.101 表示:1/2 + 0/4 + 1/8
每位权重是:1/2, 1/4, 1/8…(即2的负幂次)
乘以2的原理
乘以2的作用是"查看当前位是0还是1":
1)乘以2相当于把二进制数左移一位
例如:0.101 × 2 = 1.01(小数点右移)
2)整数部分就会告诉我们这一位是0还是1
1.01的整数部分是1 → 这一位是1
然后去掉整数部分继续处理小数部分
3)重复这个过程就能逐位得到二进制表示
实际例子:0.625转二进制
1)0.625 × 2 = 1.25 → 整数部分1(第一位是1),剩下0.25
2)0.25 × 2 = 0.5 → 整数部分0(第二位是0),剩下0.5
3)0.5 × 2 = 1.0 → 整数部分1(第三位是1),剩下0.0(结束)
所以0.625的二进制是0.101
为什么0.72会出错
因为0.72在二进制中是无限循环的:
0.72 × 2 = 1.44 → 1
0.44 × 2 = 0.88 → 0
0.88 × 2 = 1.76 → 1
…
这个过程永远不会归零,所以32位内无法精确表示。
5. 运行结果:
二进制表示: 0.101
二进制表示: ERROR
感谢您的阅读。原创不易,如您觉得有价值,请点赞,关注。