`
yaojingguo
  • 浏览: 208941 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Big Integer Arithmetic

阅读更多

A refinement of http://fuliang.iteye.com/blog/368928 .

 

#include <string>
#include <iostream>
using namespace std;

/*
 * This implementation uses string to represent big integer. Arithmetic is 
 * performed on every digit. This is not a efficient way. Hacker's Delight 
 * provides a more efficient way. If I am not wrong, Java BigInteger performs 
 * arithmetic in that way.
 */

// ascii code for '0'
const int ZERO = 48;

inline int compare(string str1, string str2) {
  int result = str1.size() - str2.size();
  if (result != 0) 
    return result;
  else
    return str1.compare(str2);
}

inline int int_val(const char& ch) {
  return ch - ZERO;
}

inline void swap_str(string& str1, string& str2) {
  string temp = str1;
  str1 = str2;
  str2 = temp;
}

inline char ch_val(int integer) {
  return char(integer + ZERO);
}

inline bool negative(string str) {
  return str[0] == '-';
}

inline bool same_sign(string str1, string str2) {
  return str1[0] == '-' && str2[0] == '-' 
    || str1[0] != '-' && str2[0] != '-';
}

inline void format(int sign, string& integer) {
  integer.erase(0, integer.find_first_not_of('0'));  
  if(integer.empty()) integer = "0";  
  if((sign == -1) && (integer[0] != '0'))  
    integer = "-" + integer;  
}

string add_int(string, string);
string subtraction_int(string, string);
string add_natural(string, string);
string subtraction_natural(string, string);

/**
 * add_int - add two integers.
 */
string add_int(string lterm, string rterm) {
  int sign = 1;
  string sum;

  if (same_sign(lterm, rterm)) {
    if (negative(lterm)) {
      sign = -1;
      lterm.erase(0, 1);
      rterm.erase(0, 1);
    }
    sum = add_natural(lterm, rterm);
  } else {
    if (negative(lterm))
      swap_str(lterm, rterm);
    rterm.erase(0, 1);

    int res = compare(lterm, rterm);
    if (res == 0)
      return "0";
    else if (res < 0) {
      sign = -1;
      swap_str(lterm, rterm);
    }
    sum = subtraction_natural(lterm, rterm);
  }

  format(sign, sum); 
  return sum;  
}

/**
 * subtraction_int - subtract rterm from lterm.
 */
string subtraction_int(string lterm, string rterm) {
  if (negative(rterm))
    rterm.erase(0, 1);
  else 
    rterm = "-" + rterm;
  return add_int(lterm, rterm);
}

/**
 * subtraction_natural - subtract rterm natural number from lterm natural number.
 * 
 * rterm should be less than lterm.
 */
string subtraction_natural(string lterm, string rterm) {
  string difference;
  string::size_type offset = lterm.size() - rterm.size();

  for (int i = rterm.size() - 1; i >= 0; i--) {
    if (lterm[i + offset] < rterm[i]) {
      difference = ch_val(lterm[i + offset] - rterm[i] + 10) + difference;
      int j = i + offset - 1;
      while (lterm[j] == ZERO) {
        lterm[j--] = 9 + ZERO;
      }
      lterm[j] = char(int(lterm[j]) - 1);
    } else {
      difference = ch_val(lterm[i + offset] - rterm[i]) + difference;
    }
  }
  for (int i = offset - 1; i >= 0; i--)
    difference = lterm[i] + difference;

  return difference; 
}

/**
 * add_natural - add the two natural number.
 */
string add_natural(string lterm, string rterm) {
  int i;
  string sum;
  string::size_type ll, lr;
  ll = lterm.size();
  lr = rterm.size();
  if (ll < lr) {
    for (i = 1; i <= lr - ll; i++)
      lterm = "0" + lterm;
  } else {
    for (i = 1; i <= ll - lr; i++)
      rterm = "0" + rterm;
  }
  int digit = 0, carry = 0, temp;
  for (i = lterm.size() - 1; i >= 0; i--) {
    temp = int_val(lterm[i]) + int_val(rterm[i]) + carry;
    digit = temp % 10;
    carry = temp / 10;
    sum = ch_val(digit) + sum;
  }
  if (carry != 0)
    sum = ch_val(carry) + sum;
  return sum;
}

/**
 * multiply_int - multiply two integers.
 */
string multiply_int(string lfactor, string rfactor) {
  // handle sign
  int sign = 1;
  if (lfactor[0] == '-') {
    sign *= -1;
    lfactor = lfactor.erase(0, 1);
  }
  if (rfactor[0] == '-') {
    sign *= -1;
    rfactor = rfactor.erase(0, 1);
  }

  string product;
  int i, j;
  string::size_type l1, l2;
  l1 = lfactor.size();
  l2 = rfactor.size();

  for (i = l2 - 1; i >= 0; i--) {
    string temp;
    int digit = 0, carry = 0, product1, rdigit = int_val(rfactor[i]);
    if (rdigit != 0) {
      for (j = 1; j <= (int)(l2 - 1 - i); j++)
        temp = temp + "0";
      for (j = l1 - 1; j >= 0; j--) {
        product1 = rdigit * int_val(lfactor[j]) + carry; 
        digit = product1 % 10;
        carry = product1 / 10;
        temp = ch_val(digit) + temp;
      }
      if (carry != 0)
        temp = ch_val(carry) + temp;
      product = add_int(product, temp);
    }
  }

  format(sign, product);
  return product;
}

/**
 * divide_int - divide divident wiwht divisor.
 * @flag: 1 to return quotient, 0 to return residue.
 */
string divide_int(string divident, string divisor, int flag) {
  string quotient, residue;
  int sign1 = 1, sign2 = 1;

  // divided by zero
  if (divisor == "0") {
    quotient = "ERROR";
    residue = "ERROR";
    if (flag == 1)
      return quotient;
    else 
      return residue;
  }

  // divide zero
  if (divident == "0") {
    quotient = "0";
    residue = "0";
  }

  if (divident[0] == '-') {
    divident.erase(0, 1);
    sign1 = -1;
    sign2 = -1;
  }
  if (divisor[0] == '-') {
    divisor.erase(0, 1);
    sign1 *= -1;
  }

  int res = compare(divident, divisor);
  if (res < 0) {
    quotient = "0";
    residue = divident;
  } else if (res == 0) {
    quotient = "1";
    residue = "0";
  } else {
    string::size_type l1 = divident.size();
    string::size_type l2 = divisor.size();
    string temp;
    string product;
    temp.append(divident, 0, l2 - 1);
    for (int i = l2 - 1; i < l1; i++) {
      temp = temp + divident[i];
      // try quotient
      for (char ch = '9'; ch >= '0'; ch--) {
        string str;
        str = str + ch;
        product = multiply_int(divisor, str);
        if (compare(product, temp) <= 0) {
          quotient = quotient + ch;
          temp = subtraction_int(temp, product);
          break;
        }
      }
    }
    residue = temp;
  }

  format(sign1, quotient);
  format(sign2, residue);
  return flag ? quotient : residue;
}

string divide_int(string divident, string divisor) {
  return divide_int(divident, divisor, 1);
}

int main(int argc, const char *argv[]) {
  char ch;
  string lterm, rterm, res;
  int shift;
  
  while (cin >> ch) {
    cin >> lterm >> rterm;
    switch (ch) {
      case '+': 
        res = add_int(lterm, rterm);
        break;
      case '-':
        res = subtraction_int(lterm, rterm);
        break;
      case '*':
        res = multiply_int(lterm, rterm);
        break;
      case '/':
        res = divide_int(lterm, rterm);
        break;
      default:
        break;
    }
    cout << res << endl;
  }

  return 0;
}
0
0
分享到:
评论
1 楼 fuliang 2010-09-17  
more cleanner than before

相关推荐

    通信计算机网络面试题(c/c++)

    超长整数运算 (Big Integer Arithmetic) **说明**:超长整数运算是指处理超出普通整数范围的大整数的加减乘除等基本运算。 - **应用场景**:超长整数运算常用于密码学、高性能计算等领域。 - **实现**:通常使用...

    big_integer_numerics

    标题 "big_integer_numerics" 暗示我们讨论的主题与大整数计算有关,这通常涉及到计算机科学中的数值计算和数据类型。在编程语言如 C 中,标准整型(如 int 和 long)在处理非常大的整数时可能会遇到限制。为了解决...

    js-integer-big-endian:JavaScript的以big-endian顺序进行整数的任意精度算术

    :elephant: ... integer . parse ( 16 , 100 , 'ff' ) ; // [ 2 , 55 ] integer . stringify ( 100 , 16 , [ 2 , 55 ] ) ; // 'ff' integer . translate ( 10 , 16 , '255' ) ; // 'ff' :scroll: 参考

    miracl大数运算库使用手册.doc

    MIRACL(Multiprecision Integer and Rational Arithmetic C/c++ Library)是一套由 Shamus Software Ltd. 所开发的一套关于大数运算函数库,用来设计与大数运算相关的密码学之应用。该库包含了 RSA 公开密码学、...

    miracl中文使用手册

    MIRACL(Multiprecision Integer and Rational Arithmetic C/C++ Library)是一套由 Shamus Software Ltd.所开发的关于大数运算函数库,用来设计与大数运算相关的密码学之应用,包含RSA 公开密码学、Diffie-Hellman ...

    mirac密码运算库

    Two new data-types are defined - big for large integers and flash (short for floating-slash) for large rational numbers. The large integer routines are based on Knuth’s algorithms, described in ...

    Java™ Puzzlers: Traps, Pitfalls, and Corner Cases.chm

    2. Integer Arithmetic 3. Floating-Point Arithmetic 4. Expression Evaluation 5. Flow of Control 6. Class Initialization 7. Instance Creation and Destruction 8. Other Class- and Instance-Related Topics...

    MIRACL用户手册(译).pdf

    MIRACL(Multiprecision Integer and Rational Arithmetic C/C++ Library)是一种多精度整数和有理数运算库,提供了一个基于C的库,用于实现高精度的整数和有理数运算。该库包含了100余个例程,涵盖了多精度运算的...

    基于miracl的大数运算,有详细的说明

    MIRACL(Multiprecision Integer and Rational Arithmetic C Library)是一个强大的、高效的、跨平台的开源库,它提供了大整数和复数的高精度计算功能,非常适合在需要处理大量数据和执行复杂数学运算的场景中使用。...

    大数运算库miracl 有了miracl这样的函数库,你可以直接调用函数,来实现你要的公钥密码学的某个功能.zip

    其中,大数运算库如MIRACL(Multiple-precision Integer and Rational Arithmetic Library)为实现复杂的加密算法提供了强大的支持。 MIRACL是一个高效且灵活的大整数运算库,专为处理大整数和复数运算而设计。它...

    BigInt-Addition.zip_SUM

    `BigInt`,全称“Big Integer”,是一种可以表示任意大整数的数据类型,通常用于处理超过普通整型变量所能承载范围的数值。在标题“BigInt-Addition.zip_SUM”中,我们看到关键词“BigInt”和“Addition”,这表明这...

    大整数问题

    在计算机科学中,大整数(Big Integer)是指超过普通数据类型(如int或long)所能表示的最大范围的整数。处理大整数是计算密集型任务,因为它们需要特殊的算法和技术来执行基本的数学运算,如加法、减法、乘法。这段...

    Java解惑(谜题)CHM中英文双版本

    Integer Arithmetic Section 3. Floating-Point Arithmetic Section 4. Expression Evaluation Section 5. Flow of Control Section 6. Class Initialization Section 7. Instance Creation and ...

    miracl英文用户介绍

    根据提供的文档信息,这里将对MIRACL(Multiprecision Integer and Rational Arithmetic Cryptographic Library)进行详细介绍,特别是关于其基本用法、重要函数的功能及其实现。 ### 1. Introduction MIRACL是由...

    miracl_demo

    MIRACL库,全称“Multiple precision Integer and Rational Arithmetic C/C++ Library”,是一款强大的多精度整数和有理数算术库,它提供了广泛的大整数和大浮点数运算功能,支持多种加密算法和数学操作,对于开发...

    C++编写大整数加减法,乘法

    此时,我们需使用大整数(Big Integer)来表示和操作超出了普通整型范围的数字。C++编程语言虽然没有内置的大整数类型,但可以通过自定义数据结构和算法来实现这一功能。本篇将重点讨论如何使用C++编写大整数的加法...

    RSA源代码实现

    在压缩包文件“RSA”中,很可能包含了上述各个步骤的C++源代码文件,如`prime_check.cpp`用于素数检测,`big_integer.cpp`用于大整数操作,`euler_phi.cpp`计算欧拉函数,`mod_inverse.cpp`求模逆元,以及`rsa_...

Global site tag (gtag.js) - Google Analytics