これは楽しい問題です。
Timonsの応答の背後にある考え方は、リーガルダブルが可能な最小の精度を表すイプシロンを指定することです。アプリケーションで0.00000001未満の精度は必要ないことがわかっている場合、彼が提案することは、真実に非常に近いより正確な結果を得るのに十分です。最大精度を事前に知っているアプリケーションで役立ちます(たとえば、通貨精度の財務など)
ただし、それを四捨五入しようとする際の基本的な問題は、係数で除算して再スケーリングすると、実際には精度の問題の別の可能性が生じることです。ダブルスを操作すると、周波数が変化すると不正確な問題が発生する可能性があります。特に、非常に有効数字で丸めようとしている場合(つまり、オペランドが0未満である場合)、たとえば、Timonsコードで次を実行する場合:
System.out.println(round((1515476.0) * 0.00001) / 0.00001);
1499999.9999999998
ここでの目標は、500000の単位で丸めることです(つまり、1500000が必要です)。
実際、不正確さを完全に排除する唯一の方法は、BigDecimalを使用してスケールオフすることです。例えば
System.out.println(BigDecimal.valueOf(1515476.0).setScale(-5, RoundingMode.HALF_UP).doubleValue());
イプシロン戦略とBigDecimal戦略を組み合わせて使用すると、精度を細かく制御できます。イプシロンであるという考えはあなたを非常に近づけ、BigDecimalはその後の再スケーリングによって引き起こされる不正確さを排除します。ただし、BigDecimalを使用すると、アプリケーションの期待されるパフォーマンスが低下します。
BigDecimalを使用して再スケーリングする最後のステップは、最終的な除算でエラーが再発生する可能性のある入力値がないと判断できる場合、一部のユースケースでは必ずしも必要ではないことが指摘されています。現在、これを適切に判断する方法がわからないので、誰かがその方法を知っていれば、それについて聞いて喜んでいます。