问题描述
我需要了解 Java / Kotlin 的人的帮助。
我想用 BigDecimal 进行一些计算
下面的表达式使用 BigDecimal 会怎样?
(1 + 0.02) ^ (1 / 251) - 1
我尝试这样做:
val x = (BigDecimal.ONE + BigDecimal(0.02)).pow(1/251) - 1
然而,1 除以 251 并不准确,这个表达式总是返回 0
解决方法
数字文字
在构造 BigDecimal
时不要使用数字文字。
如果您编写 new BigDecimal( 0.02 )
,编译器首先将这样的文字作为 float
或 double
原语进行处理。然后将生成的 float
或 double
传递给通过 BigDecimal
调用的 new
构造函数。
float
和 double
类型基于 floating-point 技术。 Floating-point trades away accuracy 用于性能(快速执行)。
因此,您使用文字会导致不准确,从而破坏了使用 BigDecimal
的两个目的中的第一个:(a) 准确性,以及 (b) 处理非常大/非常小的数字。
因此通过传递文本而不是数字来构造一个 BigDecimal
。 Java 语法示例:
new BigDecimal( "0.02" )
使用方法调用,而不是使用 Java 数学运算符
您不能将运算符 +-*/
与 BigDecimal
对象一起使用,至少在 Java 中不能(我不知道 Kotlin)。
要添加 BigDecimal
对象,请调用 plus
方法。要减去,请调用 subtract
。等等。 Java 语法示例:
BigDecimal sum = BigDecimal.ONE.plus( new BigDecimal( "0.02" ) ) ;
构造函数
使用 new
构造每个 BigDecimal
对象。您的代码 + BigDecimal(…
应该是 + new BigDecimal(…
。好吧,至少在 Java 中……再说一次,我不知道 Kotlin。
示例
你的代码,显然是用 Kotlin 编写的。
val x = (BigDecimal.ONE + BigDecimal(0.02)).pow(1/251) - 1
...应该更像这样,至少在 Java 中(相对于 Kotlin):
BigDecimal sum = BigDecimal.ONE.plus( new BigDecimal( "0.02" ) ) ;
BigDecimal exponent = BigDecimal.ONE.divide( new BigDecimal( "251" ) ;
BigDecimal pow = sum.pow( exponent ) ) ;
BigDecimal subtraction = pow.subtract( BigDecimal.ONE ) ;
请注意,我建议使用多行代码分解数学工作的各个部分。我这样做是为了使代码更易于阅读,并且更易于测试、跟踪和验证。
警告:该代码是现成的,未经测试。而且,我不是数学奇才。
警告:我忽略了四舍五入的问题。您可能想要调用使用 MathContext
来执行舍入的方法的变体,具体取决于您的工作上下文。
1 除以 251 是不准确的,这个表达式总是返回 0
这将导致整数除法,要解决整数除法,您可以执行 1.00/251
。
此外,您还缺少 new
之前的 BigDecimal(0.02)
,但即使您这样做了,+
也没有运算符 BigDecimal
,plus
方法应该使用。