過去の桐井戸端BBS (桐ver.8)
5173 除算と乗算の順序 tomo 2000/03/14-22:15
あ×い÷う

あ÷う×い
は違うんですね。

高校の学年末成績処理をしていて
「単位数×法定時数の3分の1を越える欠課時数」を
以下のように絞り込んでいました。
  &欠課時数>&法定時数÷3×&単位数
が、理屈に合わない結果がでてきまして、次のように修正
  &欠課時数>&法定時数×&単位数÷3
すると、考えていた結果になりました。

きっと、「今更」な内容でしょうが、
実際の操作で体験し、新鮮な驚きでしたので。
5183 除算による誤差の問題 佐田 守弘 2000/03/15-00:51
記事番号5173へのコメント
tomoさん
確認させて下さい。
ここで言う「あ」「い」「う」のデータ型は何でしょうか。
もし整数であると、仰られる事が起きる可能性がないとは言えません。

試していませんが、整数型で10÷3×3を計算した場合、
10÷3 → 3 (余りは切り捨て)
3×3 → 9
になると思います。

しかし、数値型であれば、桐はBCD演算をしているので、きわめて小さな誤差を除いて、同じ結果になるはずです。
ここで言うきわめて小さな誤差とは、およそ10のマイナス16乗程度の誤差です。

余談ですが付け加えておくと、MS製品その他で一時騒がれました問題、つまりバイナリ演算に起因する誤差
例えば、1/3*3が0.9999999・・・・になり、1にならない件は、桐で数値型を使う場合には発生しません。
ただし、桐でも実数型を使うと同じ問題が発生します。

桐はこの問題を避けるために、バイナリ形式ではなくBCD形式の数値型を標準としており、除算の順序による誤差の
発生をなくす様にしているそうです。
その代わり、演算速度はバイナリ演算に比べて遅くなります。

佐田守弘(KS-00119)
5185 Re:除算による誤差の問題 tomo 2000/03/15-06:20
記事番号5183へのコメント
>もし整数であると、仰られる事が起きる可能性がないとは言えません。
整数です。
上記式の右辺に使う変数や項目値の型は数値でも整数でも大丈夫なんでは?
と、思いこんでいました。

一括処理や項目計算式を総点検してみます。
5190 Re:除算による誤差の問題 悲しげ 2000/03/15-10:27
記事番号5185へのコメント
どもっ、再びtomoさん、
え〜っと、

5*4/3 → 6.6666……6
4/3*5 → 6.6666……5

この最後の誤差(有効桁数がらみ)を無しにしたいと云うことでしょうか? だとすると、

対策1)計算式を(適当な桁数で)#四捨五入関数等で括る。
対策2)優先順を明示的に指定する。
    あ*い/う  → これはこのまま左側優先
    あ*(い/う) → カッコ内を先に算出する

想像するに、一括処理において、
まず「あ*い=え」を取得して次に「え/う」とする場合と、
逆に「い/う=お」を先に取得してから「あ*お」とする場合が
混在していると云うことなんでしょうか?
とすれば、最終の値を出す時点で、適当な桁数に#四捨五入
させるのが一番簡単なように気がします。

5191 Re:除算による誤差の問題 宮城 2000/03/15-10:28
記事番号5183へのコメント
>余談ですが付け加えておくと、MS製品その他で一時騒がれました問題、つまりバイナリ演算に起因する誤差
>例えば、1/3*3が0.9999999・・・・になり、1にならない件は、桐で数値型を使う場合には発生しません。

??? 0.9999999・・・・になります。私だけ? (T_T)

5192 Re:除算による誤差の問題 悲しげ 2000/03/15-10:34
記事番号5190へのコメント
補足しますと、
最後に四捨五入させるとしても、一括処理の途中で中間値を変数に
受けているとしたら、その中間値用の変数は整数系の型ではなくて、
数値系(小数点あり)である必要があります。

5212 Re:除算による誤差の問題 tomo 2000/03/16-01:38
記事番号5191へのコメント
宮城さんは No.5191「Re:除算による誤差の問題」で書きました。
>>余談ですが付け加えておくと、MS製品その他で一時騒がれました問題、つまりバイナリ演算に起因する誤差
>>例えば、1/3*3が0.9999999・・・・になり、1にならない件は、桐で数値型を使う場合には発生しません。
>
>??? 0.9999999・・・・になります。私だけ? (T_T)
>
具体的なことを書きますと
一括処理中のコマンドで
  [単位数]=3
  絞り込み [欠課時数]>35*[単位数]/3   ……(1)
なら[欠課時数]=35は絞り込み対象外なのに
  絞り込み [欠課時数]>35/3*[単位数]   ……(2)
だとそうでないと言うことなのです。
この現象は[]を整数型にしても数値型にしても同じでした。
ひょっとして「35」という値はコンピュータに悪さをする特別の値ですか?

昔、ベーシックでピタゴラス数を探すコマンドで
  IF a~2+b~2=c~2 then …
とやるとコンピ君の計算流儀に反するので
  IF a*a+b*b=c*c then …
とせよ、というのを習った気がします。
それと同様な流儀で考えなければならならないかなあと、思ってます。
きっとこれは桐のバグなんぞというものでなく、
電子計算機で数値処理をする人間が、思いこみでなく検証していくべき事なんだと思います。

いずれにせよ、(2)の順序に変えて必要な処理は終えました。
が、面白い題材だと思ったのでしつこく書いています。



5215 Re:除算による誤差の問題 悲しげ 2000/03/16-10:36
記事番号5212へのコメント
どもっ、tomoさん、

>ひょっとして「35」という値はコンピュータに悪さをする特別の値ですか?

いえ、「悪さ」と云うのでしたら、むしろ「/3」の方でしょうね。(^^;)

>一括処理中のコマンドで
>  [単位数]=3
>  絞り込み [欠課時数]>35*[単位数]/3   ……(1)
>なら[欠課時数]=35は絞り込み対象外なのに
>  絞り込み [欠課時数]>35/3*[単位数]   ……(2)
>だとそうでないと言うことなのです。
>この現象は[]を整数型にしても数値型にしても同じでした。

ここの記述が変ですね。(?_?)
電卓で計算しても(桐の項目計算式でも)
(1)35*3/3=35
(2)35/3*3=34.9999……
となります。
ひょっとして計算式の記述に次のように=が入ってるとか?(爆笑)

  絞り込み [欠課時数]>=35*[単位数]/3   ……(1)
  絞り込み [欠課時数]>=35/3*[単位数]   ……(2)

こうだとすると(1)では該当し、(2)では該当しないことになり、つじつまが合います。

いずれにせよ「/3」の呪縛から逃れるためには次のようにしたらいい
んじゃないでしょうか。これだと(1)(2)とも同じ結果を返します。
(1)#四捨五入(35*[単位数]/3,0)
(2)#四捨五入(35/3*[単位数],0)
 ※ 多分前者の方が計算が微かに速くなると思う。

ps:
余談です。TOMOさまと云う方にある件でメール送ってます。もしこの
tomoさまに届いていないとしたら、この二人は別人28号ですね。

5216 Re:除算による誤差の問題 宮城 2000/03/16-11:05
記事番号5215へのコメント
>ここの記述が変ですね。(?_?)

35>35         ……否
35>34.9999……  ……正

だから、変でもないように見えますが。(佐田さんのコメントは別途確認要。)

それ以外、悲しげさんのおっしゃるとおりと思います。

ただ、私でしたら右辺の結果を別項目にとってそれと比較するでしょう。

5218 Re:除算による誤差の問題 宮城 2000/03/16-12:27
記事番号5216へのコメント
佐田さんのコメント

>余談ですが付け加えておくと、MS製品その他で一時騒がれました問題、つまり
>バイナリ>演算に起因する誤差 例えば、1/3*3が0.9999999・・・・になり、
>1にならない件は、桐で数値型を使う場合には発生しません。ただし、桐でも
>実数型を使うと同じ問題が発生します。

ですが、どうも結果として逆のようです。

実数は誤差を含みうる近似値であることにより、1/3*3が1になる。数値は
1/3の時点で0.333333……となってしまい(もう1/3の結果そうな
ったことは忘れた)、これに3をかければそれは0.999999……ですわな、
と。

こんな感じのようですね。数値を使った上で四捨五入等で端数の扱いを決めてお
くのがよろしいようですね。

5219 Re:除算による誤差の問題(余談) 悲しげ 2000/03/16-12:39
記事番号5216へのコメント
どもっ、宮城さん、

>だから、変でもないように見えますが。

あ、そうか。(^^;)
算数は小学生の頃から苦手でした。(^^;)
しかしながら大学は理系に行ってしまい(昔は理系でも5科目あって国語系で点数を稼いで入れた)、
大学1年の数学の単位を取るのに何と3年かかりました。(^^;)
宮城さんは文系なのに、算数強いじゃないですか!(わらひ)

5227 やはり/3*3と*3/3は別の結果になっちゃいます tomo 2000/03/16-21:59
記事番号5215へのコメント
>>ひょっとして「35」という値はコンピュータに悪さをする特別の値ですか?
19でもそうでした。11でもそうでした。
除算で整除できない値に対しては必ずそうなる!!

再掲させていただきます。
>>一括処理中のコマンドで
>>  [単位数]=3
>>  絞り込み [欠課時数]>35*[単位数]/3   ……(1)
>>なら[欠課時数]=35は絞り込み対象外なのに
>>  絞り込み [欠課時数]>35/3*[単位数]   ……(2)
>>だとそうでないと言うことなのです。
>>この現象は[]を整数型にしても数値型にしても同じでした。
35でなくても3でなくても型を実数型にしても
同様の結果が得られたんです。
自宅でも職場でも。

実際に桐を立ち上げ、キーボードをたたいてやってみてください。お願いします。
項目は整数型、数値型、実数型なんぞを取りそろえ、
レコードは全項目に1がはいるやつと2が入るヤツのふたつもあれば
十分この変な結果が検証できると思うんですけれども。

レコード番号 整数型 数値型 実数型 長整数型
 1       1   1   1    1
 2       2   2   2    2

ファイル名は是非とも「やはり/3*3と*3/3は別の結果になっちゃいます」です。

でもって
 絞り込み [整数型]>1*3/3
とやれば、2だけが選ばれ
 絞り込み [整数型]>1/3*3
だと、1も2もでてきちゃう!!
確かめてみて欲しいものです。

桐8sp4です。

5229 すこーしだけ本当に訂正 tomo 2000/03/16-22:22
記事番号5227へのコメント
>除算で整除できない値に対しては必ずそうなる!!
うそです。
除数が4,5,8,10,16、20,25など
小数第n位で割り切れるときには「/n*n」は悪さをしません

まだ十分に検証してませんが、
 商が無限小数となる除数に対してそうなる
に、とりあえず訂正させていただきます
 6,7,9,11,12,13,14,15,17、18,19,21,22,…
などは除数3と同じ変な結果に、私は、なりました。
5230 Re:すこーしだけ本当に訂正 hidetake 2000/03/16-22:48
記事番号5229へのコメント
この辺については、酒井本の P155-157 に詳しく書いてあるの
ですが、Windows 版になっても変わりは無いと思います。

要約すると、1つの計算式の中では、優先順位の高いものから
順に計算される。同じ優先順位の演算子が並ぶ場合は、左から
順に計算される。括弧で括られた部分の計算は、優先順位に
関係なく最初に行われる。

と言うことで、*と/は優先順位は同じですが、左から計算
されるので、掛けてから割るか、割ってから掛けるかでは結果
が異なってきます。

あとこの桐2時代の本では、数値演算は整数型でも通貨型でも
いったん数値型(パックドデシマル)に変換して計算される。
そして、結果が保存される際に再び整数型または通貨型として
変換される。
と有りますので、整数型の値と比較しても計算上は数値型と比較しても一緒になるはずです。

計算式の優先順位は、算術演算子>比較演算子>論理演算子で
算術演算子の中の優先順位は、桐のヘルプの算術演算子の項目
に書かれています。


5231 Re:やはり/3*3と*3/3は別の結果になっちゃいます 悲しげ 2000/03/16-23:13
記事番号5227へのコメント
どもっ、tomoさん、数値型・実数型云々のことはよく判りませんが、
「やはり/3*3と*3/3は別の結果になっちゃいます」と云う点につい
ては、#5215で例示したように、私はむしろ当然のことだと思ってい
ます。
で、どうやらtomoさんは一貫して割られる数(分子)の方を、色々
数字を挙げられて、問題視しているように見えるのですが、問題の
所在は割る数(分母)の方にあるはずなんですが。
あと計算式はカッコで括らない限り、左から先に評価されますから、
データの処理上で、どうしても逆になるケースもあると云うことで
したら、最終的には#四捨五入で判断させるのが実用的だと思います。

ps:
拙稿の#5215へのコメントとして引用がありますが、あの引用部は
全く私の意見ではありません。私の主意は、#5215後段の方にあります。
趣旨が伝わっていないのかと不思議に思い、同じことの繰り返しに
近いような気もしたのですが、再度コメントさせていただいた次第。(^^;)

5232 Re:やはり/3*3と*3/3は別の結果になっちゃいます 佐田 守弘 2000/03/16-23:37
記事番号5227へのコメント
tomoさん、皆さん
私が#5133で書きました

>1/3*3が0.9999999・・・・になり、1にならない件は、桐で数値型を使う場合には発生しません。

に付きましては例が不適切でした。
桐がBCD演算を行っている事と、以前に浮動小数点演算に基づく誤差が発生する事
(Pentiumのエラッタ問題ではありません)が問題となり、何ゆえにBCD演算をしていないのかが
話題になった事は事実ですが、上記に挙げた例はふさわしくなかった様です。
取り上げられていたのは別の計算だったと思います。
確か過去の日経パソコンか日経サイエンスあたりに載っていたと思います。
(時期はおぼろげながらの記憶では、kirijournalに成績の集計の記事を書いていた頃でした。)

BCD演算を行っても、1/3は、0.333333333・・・・・・になり、最後の桁で切り捨てが発生するために1/3*3は、
1にならないんですね。
これは浮動小数点演算のためのエラーとは別物の様です。
3で割る限りBCD演算でも切り捨てエラーが発生してしまうのは避けられない様です。
おそらく、悲しげさんが書かれている様に、どこかの位置で四捨五入を行うか、
かけ算を先に済ませ、最後に割り算を行うなどの工夫が必要になるかと考えます。

この件についてはもう少し詳しく調べてから改めて御報告させて頂きたいと考えます。

佐田守弘(KS-00119)

追伸:

なお、tomoさんが#5212で書かれております
>昔、ベーシックでピタゴラス数を探すコマンドで
>IF a~2+b~2=c~2 then …
>とやるとコンピ君の計算流儀に反するので
>IF a*a+b*b=c*c then …
は、私もFORTRANの授業で習った記憶があります。ただしその理由は論議中の課題とは別でして、
「累乗演算は計算時間が掛るから、かけ算で行う方が速度が速い」でした。
またBASICの場合には、累乗や関数演算では単精度演算になるので、掛け算で行った方が倍精度演算が
できるという話もあった様に思います。
確か、桐も算術関数の精度は単精度演算程度しかなかった様に思いましたが。
5233 Re:除算と乗算の順序(報告) coffee 2000/03/17-09:05
記事番号5173へのコメント
tomoさん 皆さん こんにちは

いつも大変興味深く掲示板を拝見させて頂いています。
このコメントツリーも演算の順序の勉強になります。
なかなか面白くて感想をコメントします。

>高校の学年末成績処理をしていて
>「単位数×法定時数の3分の1を越える欠課時数」を
>以下のように絞り込んでいました。

と言うことですが、日本語の問題として、「(単位数×法定時数)の3分の1」
なのか、「単位数×(法定時数の3分の1)」なのか、どっちかなと思いました。
成績処理については全然分からないので頓珍漢な疑問でスミマセン。
私の子供が小学2年で(春から3年)学校のテストとかで、"かける数""かけられる
数""わる数""わられる数"とかが厳しくて、特に文章題を式にする時、その順番に
ついては口を酸っぱくして入っているので、ちょっとばかり気になりました。
tomoさんの言わんとしていることとは関係ないですが、皆さんのコメントを読ん
でいるうちに連想したので、コメントしました。
それでは、どうもお邪魔しました。

戻る