bounty还有3天到期。此问题的答案有资格获得+200声望奖励。ZeunO8正在寻找一个答案从一个有信誉的来源。
我正在开发一个BigNumber
库,它允许创建大数字(整数和浮点数)。您可以找到公共存储库here
我已经实现了BigFloating
和BigInteger
的加法和减法,但是乘法和除法只用于BigInteger
浮点数的位存储在std::vector
中,格式为:sign (1 bit)|binary integer(variable bits)|binary fraction(variable bits)
使得数字5.5
将具有位0 101 1
这种格式的数字乘除有哪些算法?
即
(5.5) 101 1
* (5.5) 101 1
-------------
= (30.25) 11110 01
或
(5.5) 101 1
/ (5.5) 101 1
-------------
= (1) 1
要实现的功能可以在BigCommon.cpp
中找到,它们是:std::tuple<std::vector<bool>, size_t, size_t> BigCommon::multiplyBits(const std::vector<bool> &lhsBits, const std::vector<bool> &rhsBits, const size_t &integerBitsSize, const size_t &mantissaBitsSize)
和std::tuple<std::vector<bool>, size_t, size_t> BigCommon::divideBits(const std::vector<bool> &lhsBits, const std::vector<bool> &rhsBits, const size_t &integerBitsSize, const size_t &mantissaBitsSize)
更新
我已经实现了multiplyBits算法如下:
std::tuple<std::vector<bool>, size_t, size_t> BigCommon::multiplyBits(const std::vector<bool> &lhsBits, const std::vector<bool> &rhsBits, const size_t &integerBitsSize, const size_t &mantissaBitsSize)
{
std::vector<bool> result;
result.insert(result.begin(), lhsBits[0] ^ rhsBits[0]);
size_t newIntegerBitsSize = 0;
size_t newMantissaBitsSize = mantissaBitsSize + mantissaBitsSize;
std::vector<bool> lhsBinary(lhsBits.begin() + 1, lhsBits.end());
std::vector<bool> rhsBinary(rhsBits.begin() + 1, rhsBits.end());
std::vector<bool> multResult = multiplyBinaryVectors(lhsBinary, rhsBinary);
newIntegerBitsSize = multResult.size() - newMantissaBitsSize;
result.insert(result.begin() + 1, multResult.begin(), multResult.end());
return {result, newIntegerBitsSize, newMantissaBitsSize};
};
现在只是为了分裂!
更新2
我已经使用以下算法成功地实现了除法:
std::tuple<std::vector<bool>, size_t, size_t> BigCommon::divideBits(const std::vector<bool> &lhsBits, const std::vector<bool> &rhsBits, const size_t &integerBitsSize, const size_t &mantissaBitsSize)
{
if (lhsBits.size() != integerBitsSize + mantissaBitsSize + 1 || rhsBits.size() != integerBitsSize + mantissaBitsSize + 1)
{
throw std::invalid_argument("Invalid input sizes");
}
bool lhs_sign = lhsBits[0];
bool rhs_sign = rhsBits[0];
std::vector<bool> lhs_combined(lhsBits.begin() + 1, lhsBits.end());
std::vector<bool> rhs_combined(rhsBits.begin() + 1, rhsBits.end());
// Shift the dividend left by mantissa size
std::vector<bool> lhs_shifted(lhs_combined);
lhs_shifted.insert(lhs_shifted.end(), mantissaBitsSize, false);
// Perform binary long division
std::vector<bool> quotient = divideBinaryVectors(lhs_shifted, rhs_combined);
// Determine the binary point position in the quotient
int binary_point_pos = integerBitsSize + mantissaBitsSize;
// Include the sign bit in the result
const bool sign = lhs_sign ^ rhs_sign;
std::vector<bool> result_bits = {sign};
result_bits.insert(result_bits.end(), quotient.begin(), quotient.end());
return std::make_tuple(result_bits, binary_point_pos, mantissaBitsSize);
};
更新3
经过一些测试,我发现除法算法不适用于某些类型的数字,这里有一些测试用例:5 / 0.27
10 / 100
。我还需要一些组织的指导
1条答案
按热度按时间k10s72fa1#
你所描述的是一个二进制 * 固定 * 点表示,在固定二进制点(整数和小数位之间的分割)的上方和下方都具有可变(无界)大小。
对于这种表示,乘法非常简单--只需将每个数字的整数位和小数位连接起来,相乘,然后再次拆分为整数/小数。如果输入的数字分别有 j 和 k 小数位,则结果将有 j+k 小数位。
除法比较难,因为当结果不能用二进制精确表示时,你需要决定继续除法多远(多少额外的小数位)来计算。从根本上说,它只是长除法--连接整数/分数位,除法(一个可能不会终止的过程),然后分割结果。例如,10/5。5给你
在结果中具有重复的10位值。你需要决定什么时候要截断它并对分数进行四舍五入。