如何在C++; 我想在C++中实现一个大的int类作为一个编程练习——一个可以处理比长int大的数字的类。我知道已经有好几个开源的实现了,但是我想自己写。我在试着了解什么是正确的方法
我知道一般的策略是将数字作为字符串,然后将其分解为较小的数字(例如,单个数字),并将其放入数组中。此时,实现各种比较运算符应该相对简单。我主要关心的是如何实现加法和乘法之类的东西如何在C++; 我想在C++中实现一个大的int类作为一个编程练习——一个可以处理比长int大的数字的类。我知道已经有好几个开源的实现了,但是我想自己写。我在试着了解什么是正确的方法,c++,biginteger,bignum,largenumber,C++,Biginteger,Bignum,Largenumber,我知道一般的策略是将数字作为字符串,然后将其分解为较小的数字(例如,单个数字),并将其放入数组中。此时,实现各种比较运算符应该相对简单。我主要关心的是如何实现加法和乘法之类的东西 我正在寻找一种与实际工作代码相反的通用方法和建议。一旦你在数组中有了数字,你就可以像直接做加法和乘法一样做加法和乘法。使用你在一年级到四年级学到的算法。 从“一”列开始,然后是“十”,依此类推。不要忘记,您不需要将自己限制为0-9作为数字,即使用字节作为数字(0-255),并且您仍然可以像处理十进制数字一样进行长时间的
我正在寻找一种与实际工作代码相反的通用方法和建议。一旦你在数组中有了数字,你就可以像直接做加法和乘法一样做加法和乘法。使用你在一年级到四年级学到的算法。
从“一”列开始,然后是“十”,依此类推。不要忘记,您不需要将自己限制为0-9作为数字,即使用字节作为数字(0-255),并且您仍然可以像处理十进制数字一样进行长时间的算术运算。你甚至可以使用一个长的数组,考虑一个大的int类:
但是对于乘法,您可以尝试如果您的目标体系结构支持数字的BCD(二进制编码十进制)表示,您可以获得一些硬件支持,以支持您需要执行的直接乘法/加法。让编译器发出BCD指令是您必须仔细阅读的内容
摩托罗拉68K系列芯片就是这样。我不认为使用字符串是正确的方法——尽管我自己从未编写过代码,但我认为使用基本数字类型的数组可能是更好的解决方案。其思想是,您可以简单地扩展您已有的内容,就像CPU将单个位扩展为整数一样 例如,如果您有一个结构
typedef struct {
int high, low;
} BiggerInt;
然后,您可以手动对每个“数字”(本例中为高和低)执行本机操作,注意溢出情况:
BiggerInt add( const BiggerInt *lhs, const BiggerInt *rhs ) {
BiggerInt ret;
/* Ideally, you'd want a better way to check for overflow conditions */
if ( rhs->high < INT_MAX - lhs->high ) {
/* With a variable-length (a real) BigInt, you'd allocate some more room here */
}
ret.high = lhs->high + rhs->high;
if ( rhs->low < INT_MAX - lhs->low ) {
/* No overflow */
ret.low = lhs->low + rhs->low;
}
else {
/* Overflow */
ret.high += 1;
ret.low = lhs->low - ( INT_MAX - rhs->low ); /* Right? */
}
return ret;
}
BiggerInt添加(常量BiggerInt*lhs,常量BiggerInt*rhs){
比格林特;
/*理想情况下,您需要一种更好的方法来检查溢出情况*/
如果(右侧->高<内部最大值-左侧->高){
/*使用可变长度(实数)BigInt,您可以在这里分配更多的空间*/
}
ret.high=lhs->high+rhs->high;
如果(右侧->低<内部最大值-左侧->低){
/*无溢出*/
ret.low=lhs->low+rhs->low;
}
否则{
/*溢出*/
ret.high+=1;
ret.low=lhs->low-(INT_MAX-rhs->low);/*对吗*/
}
返回ret;
}
这是一个有点过于简单的示例,但是如何扩展到一个具有可变数量的任何基数值类的结构应该是相当明显的 我的出发点是拥有一个任意大小的整数数组,使用31位和32n'd作为溢出 起始op是ADD,然后使用2的补码使其为负。在那之后,减法的流程很简单,一旦你有了add/sub,其他的一切都是可行的
可能还有更复杂的方法。但这将是数字逻辑的幼稚方法。关于这一点有完整的章节:[计算机编程的艺术,第2卷:半数值算法,第4.3节多精度算术,第265-318页(第3版)]。你可以在第四章“算术”中找到其他有趣的材料 如果您真的不想看另一个实现,您是否考虑过要学习什么?要犯的错误数不胜数,揭露这些错误既有指导意义,也很危险。在确定重要的计算经济性和拥有适当的存储结构以避免严重的性能问题方面也存在挑战 一个挑战性的问题:您打算如何测试您的实现,以及您打算如何证明它的算法是正确的 您可能希望测试另一个实现(不考虑它是如何实现的),但要想在不期望测试达到令人满意的水平的情况下进行推广,需要更多的时间。不要忘记考虑失效模式(内存不足、堆栈问题、运行时间过长等)。 玩得开心 有趣的挑战。:) 我假设你想要任意长度的整数。我建议采取以下办法: 考虑数据类型“int”的二进制性质。考虑使用简单的二进制操作来模拟CPU中的电路在添加内容时所做的操作。如果你感兴趣更深入,考虑阅读。你会做一些类似的事情,但你可以降低到那样的低水平-但由于懒惰,我想我应该放弃,找到一个更简单的解决方案 但在讨论任何关于加法、减法、乘法的算法细节之前,让我们先了解一些数据结构。当然,一种简单的方法是将内容存储在std::vector中
template< class BaseType >
class BigInt
{
typedef typename BaseType BT;
protected: std::vector< BaseType > value_;
};
template
类BigInt
{
typedef-typename-BaseType-BT;
受保护:标准::向量值;
};
您可能想考虑是否要生成一个固定大小的向量,如果要预分配它。这是为什么
template< class BaseType >
BigInt< BaseType >& BigInt< BaseType >::operator += (BigInt< BaseType > const& operand)
{
BT count, carry = 0;
for (count = 0; count < std::max(value_.size(), operand.value_.size(); count++)
{
BT op0 = count < value_.size() ? value_.at(count) : 0,
op1 = count < operand.value_.size() ? operand.value_.at(count) : 0;
BT digits_result = op0 + op1 + carry;
if (digits_result-carry < std::max(op0, op1)
{
BT carry_old = carry;
carry = digits_result;
digits_result = (op0 + op1 + carry) >> sizeof(BT)*8; // NOTE [1]
}
else carry = 0;
}
return *this;
}
// NOTE 1: I did not test this code. And I am not sure if this will work; if it does
// not, then you must restrict BaseType to be the second biggest type
// available, i.e. a 32-bit int when you have a 64-bit long. Then use
// a temporary or a cast to the mightier type and retrieve the upper bits.
// Or you do it bitwise. ;-)
//Number = 100,000.00, Number Digits = 32, Decimal Digits = 2.
BigDecimal *decimal = new BigDecimal("100000.00", 32, 2);
decimal += "1000.99";
cout << decimal->GetValue(0x1 | 0x2) << endl; //Format and show decimals.
//Prints: 101,000.99