桁数の大きい数字どうしの割り算を暗算する方法

桁数の大きい数字どうしの割り算を暗算する現実的な方法を思いついたので紹介します。筆者はこの方法で60桁÷30桁の暗算に成功しました。この方法は桁数の大きい数どうしの掛け算をする方法と関わりが深いのでまずはこちらの記事を読んだ方が良いかもしれません。

桁数の大きい数字どうしの掛け算を暗算する方法 - itleigns’s diary

はじめに

掛け算と同じですがこの記事で言う暗算は答え以外の数字を何も記入しないで問題を解くということです。問題文を覚えないので暗算中に問題文を見る必要があります。答えも全部は覚えないので計算した部分を出力して別の部分を計算するを繰り返します。 また出力した答えの一部も他の部分を計算するときに見ます。またこちらは割り算のみに関してですがこの方法は全ての場合に対応できるわけではありません。割られる数が割る数で割り切れないといけないし割る数の値が0でない1番下の位が1,3,7,9のいずれかでないといけません。

前提

上で挙げた4つの数1,3,7,9と0,1,...,9を掛けた数を見てみましょう。以下のようになります。

0 1 2 3 4 5 6 7 8 9
1 0 1 2 3 4 5 6 7 8 9
3 0 3 6 9 12 15 18 21 24 27
7 0 7 14 21 28 35 42 49 56 63
9 0 9 18 27 36 45 54 63 72 81

行ごとに1の位が0,1,...,9なものが丁度1つずつあることが分かります。この性質を使っていきます。

方法

まず割られる数をA割る数をBとします。上でも述べた通りABの倍数でBの値が0でない1番下の位が1,3,7,9の場合のみを考えます。

ABの倍数のときを考えているのでBの末尾にある0の数だけAの末尾に0があります。A,Bの末尾から0を同じ数だけ取り除いても答えが変わらないのでBの末尾にある0の数だけA,Bの末尾から0を取り除きます(つまりないものとみなして計算します。)。そうするとBは1の位が1,3,7,9のいずれかになるので以下この場合のみを考えます。

まず6桁÷3桁の割り算で例を示します。掛け算とやっていることはほとんど同じなので掛け算に対応させてA が679841でBが797の場合を計算してみます。答えをCとするとCの桁数は(6-3+1)以下なのでC=c_3c_2c_1c_0と書けます。

f:id:itleigns:20200606172142p:plain:w500

上の式を満たすようにc_3c_2c_1c_0を決めていきます。まずBの1の位とCの1の位の積の1の位がAの1の位になるようにCの1の位を決めます。7 × 3 = 21なのでc_0は3に決まります。後で使うので21を10で割った商の2を覚えておきます。

f:id:itleigns:20200606182632p:plain:w500

覚えておいた2とBの10の位とCの1の位の積とBの1の位とCの10の位の積の和の1の位がAの10の位になるようにCの10の位を決めます。2 + 9 × 3 + 7 × 5 = 64なのでc_1 は5に決まります。後で使うので64を10で割った商の6を覚えておきます。

f:id:itleigns:20200606184235p:plain:w500

覚えておいた6とBの100の位とCの1の位の積とBの10の位とCの10の位とBの1の位とCの100の位の積の和の1の位がAの100の位になるようにCの100の位を決めます。6 + 7 × 3 + 9 × 5 + 7 × 8 = 128なのでc_2は8に決まります。後で使うので128を10で割った商の12を覚えておきます。

f:id:itleigns:20200606214258p:plain:w500

覚えておいた12とBの100の位とCの10の位の積とBの10の位とCの100の位の積とBの1の位とCの1000の位の積の和の1の位がAの1000の位になるようにCの1000の位を決めます。12 + 7 × 5 + 9 × 8 + 7 × 0 = 119なのでc_3 は0に決まります(この場合答えが3桁ということなので0は出力しません)。

f:id:itleigns:20200606213915p:plain:w500

このように答えの853が求まりました。だいたいイメージはつかめましたでしょうか? 疑似コードにしてみるとこのようになります。ただし find(a,b,c)はa + b × dの1の位がcになる0,1,...,9の数dを返します。

入力
 a_{n-1}a_{n-2}\cdots a_0
 b_{m-1}b_{m-2}\cdots b_0
出力
a_{n-1}a_{n-2}\cdots a_1a_0 \ / \ b_{m-1}b_{m-2}\cdots b_1b_0
アルゴリズム
 S := 0
 for \ \ i = 0\cdots n-m
    for \ \ j = max(0,i-m+1)\cdots i-1
       S \ := \ S \ + \ c_j \times b_{i-j}
    c_i \ := \ find(S,b_0,a_i)
    S \ := \ S \ + \ c_i \times b_0
    S \ := \ S \ / \ 10
 if \ \ c_{n-m} \ == \ 0
   return \ c_{n-m-1}c_{n-m-2}\cdots c_0
 else
   return \ c_{n-m}c_{n-m-1}\cdots c_0

考察

掛け算のときと同様の議論でこの方法で200桁÷100桁の割り算を4桁の数字を1つ覚えておくだけでできます。この方法では a_{n-1},a_{n-2},\cdots ,a_{n-m+1}の情報を使っていませんが A Bで割り切れるという条件があるので計算できます。10進法でなく p進法(p素数)なら割り切れる場合は常に計算できたのにと思います。今回扱ってないケースはおそらく下の桁から計算することができないので暗算可能だと思いますがかなり難しくなると思います。必要な演算の量は 4m倍(うまく不等式を作れば4倍くらいでできるかも)でしかも作業が複雑になると思います。

最後に

実際にこの方法で60桁÷30桁の暗算をやってみた動画です。

youtu.be