発生するさまざまな型変換は、JLS #5.6.2で指定されています。あなたの場合(抜粋):
- いずれかのオペランドが double 型の場合、もう一方は double に変換されます。
- それ以外の場合、いずれかのオペランドが float 型の場合、もう一方は float に変換されます。
では0.0410f * 123456789010d = 506172848.9223363
、0.0410f
は最初に double に変換されますが、これは必ずしも と等しいとは限りません0.0410d
。実際に試してみると、そうではないことがわかります。
double d1 = 0.041d;
double d2 = 0.041f;
System.out.println(new BigDecimal(d1));
System.out.println(new BigDecimal(d2));
出力:
0.041000000000000001720845688168992637656629085540771484375
0.041000001132488250732421875
次の例では:
0.0410f * 123456789010L = 506172832
long は float に変換されます。これは、次の例で確認できます。
float f1 = 0.0410f;
float f2 = 123456789010L;
System.out.println(new BigDecimal(f1)); // 0.041000001132488250732421875
System.out.println(new BigDecimal(f2)); // 123456790528
System.out.println(new BigDecimal(0.0410f * 123456789010L)); // 5061728768
System.out.println(new BigDecimal(f1 * f2)); // 5061728768
float / double 演算の一般的な精度については、この質問を確認してください。
最後に、BigDecimal を使用すると、正しい答えが得られます。
BigDecimal a = new BigDecimal("0.041");
BigDecimal b = new BigDecimal("123456789010");
System.out.println(a.multiply(b)); // outputs 5061728349.410