

今ある問題は足し算と掛け算とわり算のみで構成されている演算です。

[code]

    double c, m, d1, d2;
    /*それぞれに値を代入*/
    double x = (c* m + ( d1 + 1.0/ d2 )/ 2.0 )/ (c + 1.0 );
    
[/code]

という式です。この式をMaximaに投げると

[code]

    double x = (c* m + 0.5*( d1 + 1.0/ d2 ))/ (c + 1.0);
    
[/code]

と変形されます。式の整理を行うと

[code]

    double x = (2.0* c* d2* m + d1* d2 + 1.0)/ ((2.0* c + 2.0)* d2);
    
[/code]

のようになります。

そのまま打ち込めば式を間違えることがないのですが  
計算誤差まで考慮して式変形をするとなると

割り算や掛け算による誤差が大きいのか  
足し算や引き算による誤差が大きいのか

を考える必要があると感じました  
どちらの演算子が少ない状態のほうが計算誤差が発生しにくいですか

* * *

追記

書籍「数値計算の常識」には式変形により誤差を回避できる例が挙げられているが具体的にどのように式を変形することが誤差の軽減につながるかについては書かれていない。（特に割り算掛け算について）  
多倍長演算や加算アルゴリズムの詳解を期待しているのではなく  
この質問では式変形により軽減できるのだとしたらどのように変形することが望ましいのかを質問しています。


CC BY-SA 3.0
2015-02-08T08:22:13.630
6142
2015-02-20T09:48:21.550
2015-02-20T03:37:33.807
question
c++ アルゴリズム
四則演算はどういう順番で実行すると計算誤差が発生/伝搬しにくいですか


**誤差** ではなく **桁落ち** でしたら加減算でしか起きません.  
それもa±bで桁落ちが起きるのはaやbの絶対値よりa±bの絶対値が何桁も0に近くなる場合のみです.  
なので, 例えば上のc,m,d1,d2が全て正なら上の3通りではいずれも桁落ちは起きません.


CC BY-SA 3.0
2015-02-08T10:11:43.977
6148
2015-02-08T10:11:43.977
5558
6142
answer


参考として 計算計算についての次のページを紹介します。

  * 数値計算アルゴリズムの例: 二次方程式 <http://macroscope.world.coocan.jp/ja/edu/computer/sabun/nizi.html>

> ...  
>  公式をそのままプログラム化したものは、仮に計算機の実数型の 有効数字が無限にあれば、正しい結果を出すはずだが、実際には有限
> であるために、誤差が生じる。これをまるめ誤差という。  
>  ...  
>  浮動小数点のまるめ誤差の問題はいろいろなところで顔を出すが、 特に、「よく似た数値の引き算」
> (あるいは、絶対値が近くて符号が反対の数のたし算)をすると 精度が落ちる。  
>  ...

  * プログラムでの小数計算で誤差を含んでしまう原因と解決方法  
<http://sasakure.hatenablog.com/entry/2013/01/06/005541>

金融関係では、わずかな計算誤差でもおおきな問題になることがあるので、いろいろ工夫がされています。


CC BY-SA 3.0
2015-02-08T21:49:19.153
6162
2015-02-08T21:49:19.153
2987
6142
answer


計算誤差で言えば、四則演算はあまり関係がありません(乗算、除算の方が影響が大きいのは確かですが)。  
どの桁まで誤差を許容できるのか次第です。

結局は`double`型を使えば誤差は生じます。  
`double value = 0.1;`  
でさえ、厳密には`0.1`を持っていません(2進数では表現できないため)。

少数第何桁まで保証したいかによってスケールを変え、整数型で計算を行うのが一般的だと思います。

たとえば、小数点第4位まで保証したければ、  
`0.1`は`1000`として扱い、最終的な演算結果に`10000`を除算し、そこで初めて`double`型に代入します。

`Maxima`のビッグフロートはこのあたりを考慮してくれているのではないですか？


CC BY-SA 3.0
2015-02-09T00:21:54.343
6165
2015-02-09T00:28:02.063
2015-02-09T00:28:02.063
7214
7214
6142
answer


「丸め誤差」「桁落ち」「情報落ち」など計算誤差に関する用語で自分なりにわかりやすいもので勉強されるのがいいと思います。

本としては、伊理正夫さんらによる「数値計算の常識」に計算誤差が詳しく書かれていたと思います。

またweb資料では[こちら](http://www.cc.kyoto-
su.ac.jp/~yamada/programming/float.html)のページは比較的よくまとめられています。


CC BY-SA 3.0
2015-02-09T01:17:04.133
6166
2015-02-09T01:17:04.133
4840
6142
answer


この式の場合についてだけ、  
cをc+1で割ることになっていて、このc+1を計算する際に桁を合わせる、つまり浮動小数の指数部をそろえる必要があり、有効桁が失われます。  
cが1から離れているほど激しく有効桁が減ります。  
コンピューターで演算するのにはあまり向かない式ですね。別の解法があるのならそれを試された方がいいのではないでしょうか。


CC BY-SA 3.0
2015-02-11T06:09:08.060
6296
2015-02-11T06:09:08.060
8136
6142
answer


厳密な保証が必要なければ、式変形する際に

  * スケール差が大きい加算・減算
  * 近い値の除算
  * doubleの四則演算

が少なくなるように配慮します。


CC BY-SA 3.0
2015-02-20T04:42:45.767
6814
2015-02-20T04:42:45.767
8431
6142
answer


> どのように式を変形することが誤差の軽減につながるかについて
>
> どちらの演算子が少ない状態のほうが計算誤差が発生しにくいですか

「数値計算の常識」で利用されている式変形は、 **誤差の補償** (compensating
errors)と言われ変数を意図的に二度以上出現されるように変形することにより行われます。

そのため、どちらかと言うと少ない状態ではなく多い状態のほうが誤差が発生しにくいことになります。

最終的に例の中から1つ選択するとしたら、cが二度出現し、d2が3度出現しているいかが適切と思われます。

[code]

    double x = (2.0* c* d2* m + d1* d2 + 1.0)/ ((2.0* c + 2.0)* d2);
    
[/code]

> 割り算や掛け算による誤差が大きいのか  
>  足し算や引き算による誤差が大きいのか

どちらが大きいとは判断できませんが、通常、割り算、掛け算では相対誤差を、足し算、引き算では絶対誤差を足し合わせることによって推定することが出来ます。


CC BY-SA 3.0
2015-02-20T09:02:41.790
6832
2015-02-20T09:48:21.550
2020-06-17T08:14:45.997
-1
6142
answer