题目描述

将一个六位以内浮点数转化为二进制。

我的思路

输入浮点数数字 $n$, 其可以转化为二进制的情况如下
$$
a_1*(\frac{1}{2})^1+a_2*(\frac{1}{2})^2+a_3*(\frac{1}{2})^3+a_4*(\frac{1}{2})^4+a_15*(\frac{1}{2})^5+a_6*(\frac{1}{2})^6=n
$$

不用考虑6次方之后的情况,因为会超出位数;
等式两边同时 $ 10^6 $
$$
500000a_1+250000a_2+…=n
10^6
$$
接下来就用 $ n*10^6 $ 从大到小依次减去a的参数,如果最后 $n$ 不为0,则返回”ERROR”;
否则返回” $0.a_1a_2a_3a_4a_5a_6$ “,最后处理一下末尾多余的0就可以了

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Solution {
public:
string printBin(double num) {
int integer_num = int (num*1000000);
vector<int> five;
int a = 1;
int b = 1000000;
for (int i=1;i<7;i++)
{
b = b/10;
a = a*5;
if (b>0)
{
five.push_back(a*b);
}
}
vector<int> ans;
b = 1000000;
for (int i=0;i<five.size();i++)
{
if (five[i]<=integer_num)
{
ans.push_back(1);
integer_num = integer_num-five[i];
}
else{
ans.push_back(0);
}
b=b/10;
}
if (integer_num>0)
{
string a ="ERROR";
return a;
}
else
{
for (int i=ans.size()-1;i>=0;i--)
{
if (ans[i]!=0)
{
break;
}
ans.pop_back();
}
string a="0.";
for (int i=0;i<ans.size();i++)
{
a += to_string(ans[i]);
}
return a;
}
}
};

缺点与优点

缺点:

1.处理情况有限;

2.字符与数字转化繁琐。

优点:

1.避开了浮点数精度丢失的问题(因为全程使用整数处理)。

官方解题思路

​ 将实数的十进制表示转换成二进制表示的方法是:每次将实数乘以2,将此时的整数部分添加到二进制表示的末尾,然后将整数部分置为0,重复上述操作,直到小数部分变成0或者小数部分出现循环时结束操作。当小数部分变成0时,得到二进制表示下的有限小数;当小数部分出现循环时,得到二进制表示下的无限循环小数。

总结

官方思路能处理的情况比我的要多很多,还在避开浮点数尾数精度不足的同时,避开了复杂的字符与数字转化。

乘2是一个非常巧妙的思想,既然十进制整数可以除以2来变形,小数乘2应该是最好的思想了