我想更好地了解“大数字”图书馆的运作方式,(例如 GMP )。
我想将自己的功能写入update:
/ Add()
/ Subtract()
/ Multiply()
传统上定义了这个类......
Divide()
首先,我需要对数字进行标准化,以便我可以做到
使用2个数字 10(x)+ 10.25(y)= 20.25
为简单起见,我会将它们设为相同的长度,
对于x: _numbers =(1,0,0,0)decimal = 2
对于y: _numbers =(1,0,2,5)decimal = 2
然后我可以在循环中反向添加x到y
std::vector<unsigned char> _numbers; // all the numbers
bool _neg; // positive or negative number
long _decimalPos; // where the decimal point is located
// so 10.5 would be 1
// 10.25 would be 2
// 10 would be 0 for example
上面的示例可用于添加两个正数,但一旦我需要将正数添加到正数,很快就会失败。
当减去数字时,这会变得更加复杂,对于乘法和除法,情况会更糟。
有人可以建议一些简单的函数来添加()/ Subtract()/ Multiply()/ Divide()
我不是要重写/改进库,我只是想了解它们如何处理数字。
答案 0 :(得分:2)
添加和减法非常简单
您需要检查操作数的符号和大小,如果需要,可以将操作转换为+/-
。我的典型C ++实现是这样的:
//---------------------------------------------------------------------------
arbnum arbnum::operator + (const arbnum &x)
{
arbnum c;
// you can skip this if you do not have NaN or Inf support
// this just handles cases like adding inf or NaN or zero
if ( isnan() ) return *this;
if (x.isnan() ) { c.nan(); return c; }
if ( iszero()) { c=x; return c; }
if (x.iszero()) return *this;
if ( isinf() ) { if (x.isinf()) { if (sig==x.sig) return *this;
c.nan(); return c; } return *this; }
if (x.isinf()) { c.inf(); return c; }
// this compares the sign bits if both signs are the same it is addition
if (sig*x.sig>0) { c.add(x,this[0]); c.sig=sig; }
// if not
else{
// compare absolute values (magnitudes)
if (c.geq(this[0],x)) // |this| >= |x| ... return (this-x)
{
c.sub(this[0],x);
c.sig=sig; // use sign of the abs greater operand
}
else { // else return (x-this)
c.sub(x,this[0]);
c.sig=x.sig;
}
}
return c;
}
//---------------------------------------------------------------------------
arbnum arbnum::operator - (const arbnum &x)
{
arbnum c;
if ( isnan() ) return *this;
if (x.isnan() ) { c.nan(); return c; }
if ( iszero()) { c=x; c.sig=-x.sig; return c; }
if (x.iszero()) return *this;
if ( isinf() ) { if (x.isinf()) { if (sig!=x.sig) return *this;
c.nan(); return c; } return *this; }
if (x.isinf()) { c.inf(); c.sig=-x.sig; return c; }
if (x.sig*sig<0) { c.add(x,this[0]); c.sig=sig; }
else{
if (c.geq(this[0],x))
{
c.sub(this[0],x);
c.sig=sig;
}
else {
c.sub(x,this[0]);
c.sig=-x.sig;
}
}
return c;
}
//---------------------------------------------------------------------------
其中:
geq
是无符号比较大于或等于add
未签名+
sub
未签名-
划分有点复杂
请参阅:
approximational bignum divider
对于部门,您需要已经实现了+,-,*,<<,>>
之类的内容,对于一些更高级的方法,您甚至需要这样的方法:绝对比较(无论如何,+/-
都需要它们), sqr ,使用的位数通常为小数和整数部分分开。
最重要的是乘法请参阅Fast bignum square computation,因为它是大多数除法算法的核心。
<强>性能强>
有些提示请参阅BigInteger numbers implementation and performance
文字转换
如果您的号码是ASCII或BASE=10^n
位数,那么这很容易,但如果出于性能原因使用BASE=2^n
,那么您需要具有能够在dec
之间进行转换的快速功能和hex
字符串,以便您可以实际加载和打印一些数字到您的班级。见: