エムゲーム・ジャパン ゲーム ミィア ブログ サークル マイエム Login

兵どもの夢の跡

ブログチャンネル
yuki002さん
 
 ブログトップ   マイブログ   ランダムブログ    
ブログ型ブログ型タイトル一覧タイトル一覧
20.桁数の問題[ソフトウェア考]  
詳細/おすすめ(3292/0) | ソーシャルブックマーク(0)  2009/09/07 01:30

久しぶりの更新です。

 

この話題は古くて新しい問題です。

そして、最近では取り扱われなくなってきてはいますが、

SEクラスの技術者では知らないと資格を疑われる内容なのです。

 

 

まず、説明や計算を簡略化するために、8ビットCPUを想定します。

ですが、それはCPUが何ビットであろうが共通する話なのです。

 

8ビットCPUですから レジスタのビット幅は8ビットです。(当然)

掛け算命令を持つCPUもありますが、CPUでは通常 整数演算 を行います。

このCPUで扱う事のできる自然な整数範囲は -128 〜 127 までです。

いくら何でも、これでは桁数が少なすぎます。

現在のCPUが32ビットなのは、これでは桁数が少なすぎて実用に不向きだからです。

 

さて、この小さなレジスタで整数演算を行う場合、どうすれば良いでしょう。

答えは簡単です。

上位の桁ろ下位の桁に分割して計算結果を合成すれば良いのです。

 

873 + 729 の計算を例に説明してみましょう。

 

873 も 729 も大きすぎてレジスタには収納できない数値ですから

これはメモリ上に置かれます。

873 と  729 を 符号無し2進数で表すと、 1101101001(2) と 1011011001(2) になり

8ビット(2進数8桁)では表現できません。

各々の下8桁とそれ以上を分離します。

 

1101101001 ⇒ 11 と 01101001

1011011001 ⇒ 10 と 11011001

 

このように分割すればレジスタに収納可能です。

ここで それぞれ桁単位で加算します。

つまり

 

11 + 10 = 101

01101001 + 11011001 = 101000010 ⇒ (105 + 217 = 322)

 

こうなります。

しかし 下8桁は桁あふれが生じます。

ですがこれは 上の桁への繰り上がりと見なせます。

そして これを合成すると8ビットでは当然足りませんので

演算結果をメモリー上に置く事になります。

 

そして 101 + 1 は 110 となり、

01000010 の上位に 110 を付けたし 11001000010 という演算結果が得られます。

11001000010 = 1602

 

数字ばかりの話でしたね。

本当は公式を書けばいいけど、それだと高等数学以上の教養も必要だしね。

とりあえず加算はこれでOKでしょ? という事は乗算もOKなわけ。

さらに乗算がOKならば 除算もOKになるし剰余も可能って事なのね。

 

さて、これで有限な桁数でそれを超える演算が可能って事が証明できましたね。

で、こういうアルゴリズムがライブラリとして装備されているから、

C言語などでは変数の型が決まっていれば演算も可能って事で、

また、それに対しての限界もあるって事なのです。

 

 

さて 現代のCPUは 32ビットや 64ビットが主流となって、

一度に簡単に演算できるようになったのは言うまでもありません。

ですが、どんなにレジスタが大きくなっても計算桁数は限界があります。

それを知っていないと思わぬところで失敗をやらかします。

 

例えば Visual Basic などで Variant型という変数があります。

文字列であれ実数、虚数、巨大な数、金額さえも扱える万能変数型なのですが、

これを過信すると酷い目に遭います。

この変数型は内部にポインタという形で領域を確保します。

そのため、巨大な数値は文字列(単なる数字の羅列)として扱われる事があるのです。

文字列として保持されているため実際には演算は不可能なのです。

それでも強制的に演算を行うとエラーになるか、有効な部分の文字コード(数値)で

演算してしまう事もあります。

 

コンピュータで扱う数値は他にも型があります。

浮動小数点型では有効数値の範囲で計算するため、計算の重複回数が増えるほど誤差が累積します。

これを極限まで抑えた金額型でさえ誤差が生じます。

いくら万能型の Variant型でもこれらの型を内臓している以上は過信は禁物という事です。

.NET になってからは Object型とされましたが内容は同じなのです。

 

 

 

ここからは愚痴です。

私が派遣に出ていた頃の話です。

正社員の方がVBにてフォームを作り、そのコードを派遣の私が書くという仕事でした。

そして発覚したのが この手のミスなのです。

演算可能な桁数を超える数値を Variant型に代入し、誤差ゼロという仕様でした。

設計者は演算可能な数値範囲を知らなかったと見えます。

しかも発見は納入テストの3日前という非常にタイトな期日でした。

私の「この仕様実現できませんよ。 文字列と数値の演算か、誤差を含む浮動小数点型と整数の演算ですが。」

「しかも VBのライブラリだけでは実現不能ですが…。」

という返答に土下座して「お願いします!」とか言ってました。

仕方ないので、急遽アセンブラでその桁数に対する演算ライブラリを作り事無きを得ましたが、

そのバカ正社員さん、自分の成果だと大威張りでしたね。

その後、それがバレてクビになったそうですが…。

 

コンピュータでは扱える数値に範囲があり、それを超える演算にはソフトウェアで対応するしか無いのです。

こういう初歩的な事に気付かないのは、基礎を疎かにした証拠としか言えませんが、

普段、こういう状況は起こりにくいので、うっかり失敗してしまうようです。

これもソフトウェアそのものにバリエーションが増え、更に専門家が増えた弊害とも言えそうです。

基本的な事とはいえ、忙殺されうっかり忘れてしまう事もあるようで、これが致命的バグにもなります。

ソフトウェアとは生産性だけが目的ではない事も知っておくべきでしょうね。

 

 

この記事のURL /  カテゴリ /  コメント(2)  / おすすめ  / 通報
   あれ? ログイン障害?
   某 腐れサイトの話