构造单精度浮点数的存储格式,这个代码还有问题,我知道为什么,但是却没办法修改它,这个代码太乱了,我实在是不想继续在其上面完善了#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <cmath>
#define BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE
#include <boost/multiprecision/cpp_int.hpp>
using BigInteger = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>>;
static const std::string IntegerPartToBinaryString(const std::string &string, size_t bits)
{
BigInteger num(string);
std::string result;
while(num)
{
if(num % 2)
result += "1";
else
result += "0";
num /= 2;
}
std::reverse(result.begin(), result.end());
if(bits)
{
while(result.size() != bits)
result.insert(result.begin(), '0');
}
if(result.size() == 0)
result += "0";
return result;
}
static const std::string RemovePrefixZero(const std::string &string)
{
auto iter = string.begin();
for(; iter != string.end(); ++iter)
{
if(*iter != '0')
break;
}
if(iter == string.end())
return std::string("0");
return std::string(iter, string.end());
}
static void BinaryCarry(std::string &string)
{
for(auto iter = string.rbegin(); iter != string.rend(); ++iter)
{
if(*iter == '0')
{
*iter = '1';
break;
}
*iter = '0';
}
}
static const std::string DecimalPartToBinaryString(const std::string &string, size_t bits)
{
BigInteger num = BigInteger(pow(10, string.size()));
num += BigInteger(RemovePrefixZero(string));
std::string result;
for(size_t i = 0; i < bits + 1; ++i)
{
num *= 2;
num -= BigInteger(pow(10, string.size()));
BigInteger remainder = (num / BigInteger(pow(10, string.size()))) % 10;
if(remainder > 1)
{
num -= BigInteger(pow(10, string.size()));
result += "1";
}
else
{
result += "0";
}
}
char ch = *(result.end() - 1);
result.erase(result.end() - 1);
if(ch == '1')
{
BinaryCarry(result);
}
return result;
}
static const std::string GetFraction(const std::string &binary_integer_part, const std::string &binary_decimal_part)
{
std::string fraction = binary_integer_part + binary_decimal_part;
fraction.erase(fraction.begin());
return fraction;
}
static const std::string GetExponent(size_t exponent, bool normalization)
{
if(!normalization)
return std::string("00000000");
BigInteger num = exponent + 127;
return IntegerPartToBinaryString(num.str(), 8);
}
static void SetBit(uint32_t &data, bool bit, size_t pos)
{
data &= ~(1 << pos);
data |= bit << pos;
}
static uint32_t MakeFloat(bool sign, const std::string &exponent, const std::string &fraction)
{
uint32_t num = 0;
SetBit(num, sign, 31);
for(int i = 30; i != 22; --i)
SetBit(num, exponent[30 - i] == '1', i);
for(int i = 22; i >= 0; --i)
SetBit(num, fraction[22 - i] == '1', i);
return num;
}
size_t ParseFloat(std::string num)
{
std::string integer_part;
std::string decimal_part;
size_t pos = num.find('.');
if(pos == std::string::npos)
{
integer_part = num;
decimal_part = "0";
}
else
{
integer_part = std::string(num.begin(), num.begin() + pos);
decimal_part = std::string(num.begin() + pos + 1, num.end());
}
std::string binary_integer_part = IntegerPartToBinaryString(integer_part, 0);
std::string binary_decimal_part = DecimalPartToBinaryString(decimal_part, 23 - (binary_integer_part.size() - 1));
std::string exponent;
if(binary_integer_part == "0")
exponent = GetExponent(binary_integer_part.size() - 1, false); // 非正规化
else
exponent = GetExponent(binary_integer_part.size() - 1, true); // 正规化
std::string fraction = GetFraction(binary_integer_part, binary_decimal_part);
return MakeFloat(num[0] == '-', exponent, fraction);
}
int main()
{
float num;
std::cout << std::hex << std::uppercase;
num = 3.14F;
std::cout << *(uint32_t *)&num << " -> " << ParseFloat("3.14") << std::endl;
num = 1234.0F;
std::cout << *(uint32_t *)&num << " -> " << ParseFloat("1234") << std::endl;
num = 3.1415926F;
std::cout << *(uint32_t *)&num << " -> " << ParseFloat("3.1415926") << std::endl;
num = 0.0F;
std::cout << *(uint32_t *)&num << " -> " << ParseFloat("0") << std::endl;
num = 0.005F;
std::cout << *(uint32_t *)&num << " -> " << ParseFloat("0.005") << std::endl;
return 0;
}
|