mk-mode BLOG

このブログは自作の自宅サーバに構築した Debian GNU/Linux で運用しています。
PC・サーバ構築等の話題を中心に公開しております。(クローンサイト: GitHub Pages

ブログ開設日2009-01-05
サーバ連続稼働時間
Reading...
Page View 合計
Reading...
今日
Reading...
昨日
Reading...

Python - 多桁計算!

[ プログラミング, 数学 ] [ Python ]

こんばんは。

Python 3 で多桁計算を行う方法についての記録です。

0. 前提条件

  • LMDE 2 (Linux Mint Debian Edition 2; 64bit) での作業を想定。
  • Python 3.6.4 での作業を想定。
  • 当方は他のバージョンとの共存環境であり、 python3.6, pip3.6 で 3.6 系を使用するようにしている。(適宜、置き換えて考えること)

1. アルゴリズムについて

当ブログ過去記事を参照。

2. Python スクリプトの作成

  • 敢えてオブジェクト指向で作成している。
  • Shebang ストリング(1行目)では、フルパスでコマンド指定している。(当方の慣習
  • 数値計算ライブラリ NumPy を使用しない。(この程度の計算では、逆に2倍程度時間がかかってしまうため)
  • 必要であれば、スクリプト内の定数を変更する。
calc_big_digits.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#! /usr/local/bin/python3.6
"""
Computation of big-digit values
"""
import sys
import traceback


class CalcBigDigits:
    N = 5

    def __init__(self):
        # a, b: for addition, subtraction
        # c, d: for multiplication, division
        self.a = [56789012,34567890,12345678,90123456,78901234]
        self.b = [12345678,90123456,78901234,56789012,34567890]
        self.c = [      12,34567890,12345678,90123456,78901234]
        self.d = 99

    def compute(self):
        """ Computation of big-digit values """
        try:
            self.__long_add()  # long + long
            self.__long_sub()  # long - long
            self.__long_mul()  # long * short
            self.__long_div()  # long / short
        except Exception as e:
            raise

    def __long_add(self):
        """ Computation of long + long """
        try:
            z = [0 for _ in range(self.N)]
            carry = 0
            for i in reversed(range(self.N)):
                z[i] = self.a[i] + self.b[i] + carry
                if z[i] < 100000000:
                    carry = 0
                else:
                    z[i] = z[i] - 100000000
                    carry = 1
            print(" ", end="")
            self.__display_l(self.a)
            print("+", end="")
            self.__display_l(self.b)
            print("=", end="")
            self.__display_l(z)
            print()
        except Exception as e:
            raise

    def __long_sub(self):
        """ Computation of long - long """
        try:
            z = [0 for _ in range(self.N)]
            borrow = 0
            for i in reversed(range(self.N)):
                z[i] = self.a[i] - self.b[i] - borrow
                if z[i] >= 0:
                    borrow = 0
                else:
                    z[i] += 100000000
                    borrow = 1
            print(" ", end="")
            self.__display_l(self.a)
            print("-", end="")
            self.__display_l(self.b)
            print("=", end="")
            self.__display_l(z)
            print()
        except Exception as e:
            raise

    def __long_mul(self):
        """ Computation of long * short """
        try:
            z = [0 for _ in range(self.N)]
            carry = 0
            for i in reversed(range(self.N)):
                w = self.c[i]
                z[i] = (w * self.d + carry) % 100000000
                carry = int((w * self.d + carry) / 100000000)
            print(" ", end="")
            self.__display_l(self.c)
            print("*", end="")
            self.__display_s(self.d)
            print("=", end="")
            self.__display_l(z)
            print()
        except Exception as e:
            raise

    def __long_div(self):
        """ Computation of long / short """
        try:
            z = [0 for _ in range(self.N)]
            remainder = 0
            for i in range(self.N):
                w = self.c[i]
                z[i] = int((w + remainder) / self.d)
                remainder = ((w + remainder) % self.d) * 100000000
            print(" ", end="")
            self.__display_l(self.c)
            print("/", end="")
            self.__display_s(self.d)
            print("=", end="")
            self.__display_l(z)
            print()
        except Exception as e:
            raise

    def __display_l(self, s):
        """ Display for a long value

        :param int s
        """
        try:
            for i in range(self.N):
                print(" {:08d}".format(s[i]), end="")
            print()
        except Exception as e:
            raise

    def __display_s(self, s):
        """ Display for a short value

        :param int s
        """
        try:
            for _ in range(self.N - 1):
                print(" " * 9, end="")
            print(" {:08d}".format(s))
        except Exception as e:
            raise


if __name__ == '__main__':
    try:
        obj = CalcBigDigits()
        obj.compute()
    except Exception as e:
        traceback.print_exc()
        sys.exit(1)

3. Python スクリプトの実行

まず、実行権限を付与。

1
$ chmod +x calc_big_digits.py

そして、実行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ./calc_big_digits.py
  56789012 34567890 12345678 90123456 78901234
+ 12345678 90123456 78901234 56789012 34567890
= 69134691 24691346 91246913 46912469 13469124

  56789012 34567890 12345678 90123456 78901234
- 12345678 90123456 78901234 56789012 34567890
= 44443333 44444433 33444444 33334444 44333344

  00000012 34567890 12345678 90123456 78901234
*                                     00000099
= 00001222 22221122 22222211 22222222 11222166

  00000012 34567890 12345678 90123456 78901234
/                                     00000099
= 00000000 12470382 72851976 55455792 49281830

以上

プログラミング, 数学 Python



« Python - ニュートン補間! Python - 円周率計算(マチンの公式)! »

Comments