试图理解简单的大数计算

时间:2015-11-22 05:12:16

标签: c++ math computation-theory bignum

我想更好地了解“大数字”图书馆的运作方式,(例如 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()

我不是要重写/改进库,我只是想了解它们如何处理数字。

1 个答案:

答案 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未签名-

划分有点复杂

请参阅:

  • bignum divisions
  • approximational bignum divider

    对于部门,您需要已经实现了+,-,*,<<,>>之类的内容,对于一些更高级的方法,您甚至需要这样的方法:绝对比较(无论如何,+/-都需要它们), sqr ,使用的位数通常为小数和整数部分分开。

    最重要的是乘法请参阅Fast bignum square computation,因为它是大多数除法算法的核心。

<强>性能

有些提示请参阅BigInteger numbers implementation and performance

文字转换

如果您的号码是ASCII或BASE=10^n位数,那么这很容易,但如果出于性能原因使用BASE=2^n,那么您需要具有能够在dec之间进行转换的快速功能和hex字符串,以便您可以实际加载和打印一些数字到您的班级。见: