|
发表于 2018-12-22 12:41:23
|
显示全部楼层
构造单精度浮点数的存储格式,这个代码还有问题,我知道为什么,但是却没办法修改它,这个代码太乱了,我实在是不想继续在其上面完善了
- #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;
- }
复制代码 |
|