

ユーザが定義した計算式（ **有理数の四則演算のみ** ）を解析し、`BigDecimal`を使って計算するプログラムを作っています。  
ここで、「計算結果は、小数点以下2桁までが、手計算での結果と一致することを保証する」という要求仕様があります。  
正確には、「手計算で小数点以下第3位を四捨五入した値」との一致です。

`BigDecimal`の`divide`メソッドは、`scale`の指定がありますが、上記の結果を保証するためには、都度の除算において、`scale`にどのような値を指定すれば良いのでしょうか？  
あるいは、根本的に保証できないのでしょうか？

結論が出ないながらも、自分で考えたことを挙げておきます。

  * 「小数点以下第3位を四捨五入」という操作が最後にあるので、結局は3桁目まで正しい状態を維持しなければならない
  * `divide`に対して`scale=3`を指定したとしても、`1/3=0.333`を3000倍すると999になってしまう。小数点以下何桁の保証どころではない。 
    * `(1/3)*3000` を `3000*1/3`に組み替えるようなことをしないと、根本的に保証できない？
    * あるいは、「 **十分に大きな**`scale`を指定しておく」という方針？
    * 例えば`scale=6`としたとき、`1/3=0.333333`、これを3000倍で`999.999`となる。小数点以下第3位を四捨五入すれば、`1000`になる。
    * 「十分に大きなscale」とは何か？ 具体的な値を定義できるか？

【追記】

  * 「このような計算式なら精度を保証できる」という制限付き仕様は実現可能か？ 
    * `(a + b) / (x * y)`のように、「除算が高々1回」かつ「除算が最後に実行される形」であれば良い？


CC BY-SA 3.0
2017-10-12T07:37:13.837
38635
2017-10-13T05:25:57.350
2017-10-13T05:25:57.350
8078
8078
question
java
BigDecimalでの計算精度を保証する方法


質問の回答にはなりませんが、分数を扱う[`org.apache.commons.math4.fraction.Fraction`](http://commons.apache.org/proper/commons-
math/userguide/fraction.html)を使うことで要求仕様は満たせませんか？

除算があるので、分子と分母を分けて考えた方が(例えば、Fractionのように分子と分母を内部的に持っているクラスを使った方)がいいように思います。

十分に大きな`scale`を指定しても、計算の順序を変えないと

[code]

    System.out.println(new BigDecimal(1).divide(new BigDecimal(3), MathContext.DECIMAL128).multiply(new BigDecimal(3)));
    
[/code]

が、`0.9999999999999999999999999999999999`になるようなことが起こるので。


CC BY-SA 3.0
2017-10-13T02:23:21.510
38659
2017-10-13T03:06:23.380
2017-10-13T03:06:23.380
21092
21092
38635
answer