问题:
Given a (decimal - e.g. 3.72) number that is passed in as a string, print the binary representation.If the number can not be represented accurately in binary, print “ERROR”.
分析:
我们这里暂时不考虑负数的情况,因为如果是负数的话,整数部分需要考虑比如2's complement,比较麻烦。我们就暂时假设都是正数。
好,做了这个假设以后,我们首先需要做的是,分离出整数部分和小数部分。这个很好办,用string.find(“.")和substr即可。分离出来以后,我们使用atoi和atof来把他们转化成int和float。这些简单的工作完成之后,我们要开始进行向二进制的转化了。
先说整数部分。整数部分转发的方法有不止一种,这里介绍一种笔者认为不错的:把这个整数跟1做and操作,如果得到的是1,则证明这个整数的rightmost那一位是1,所以我们加上一个“1”;如果是0,则证明这个整数的rightmost那一位是0,我们加上0即可。然后我们把这个数向右shift一位。
现在说小数部分。小数部分的算法是,不断地乘以二。如果结果是大于零的,则为“1”,然后把大于零的部分去掉即可;如果是小于零的,则为“0”,然后不用做任何事情。
需要注意的是,在处理整数部分时,我们是从低位到高位进行进行补位,也就是没添加一个字符,都是添加在原有字符的最左端;而小数部分刚好相反,每次都是添加在现有字符的最右端。
另一个需要注意的地方是:整数部分和小数部分循环停止的condition都是数不再大于零了,换句话说,一旦等于零了,就可以停止了。
代码:
#include <iostream>
#include <cstdlib>
using namespace std;
string convert(string a) {
bool negative = false;
size_t pos = a.find('.');
int intpart = atoi(a.substr(0, pos).c_str());
double decpart = atof(a.substr(pos).c_str());
if (intpart < 0) {
negative = true;
intpart = -intpart;
}
string intstr = "";
string decstr = "";
// for int part
while (intpart > 0) {
int decpart = intpart & 1;
if (decpart == 1)
intstr = "1" + intstr;
else
intstr = "0" + intstr;
intpart >>= 1;
}
// for decimal part
while (decpart > 0) {
if (decstr.size() > 32)
return "ERROR!";
decpart *= 2;
if (decpart >= 1) {
decstr += "1";
decpart -= 1;
}
else {
decstr += "0";
}
}
// ignore negative
return intstr + "." + decstr;
}
int main() {
string a = "19.25";
string result = convert(a);
cout << result << endl;
}