Scala和Java BigDecimal

我想在我的应用程序中从Java切换到基于Math的模块的脚本语言。 这是由于Java的可读性和function限制。

例如,在Java中我有这个:

BigDecimal x = new BigDecimal("1.1"); BigDecimal y = new BigDecimal("1.1"); BigDecimal z = x.multiply(y.exp(new BigDecimal("2")); 

如您所见,如果没有BigDecimal运算符重载,简单的公式会很快变得复杂。

有了双打,看起来很好,但我需要精确度。

我希望Scala能做到这一点:

 var x = 1.1; var y = 0.1; print(x + y); 

默认情况下,我会得到类似十进制的行为,唉,Scala默认情况下不使用十进制计算。

然后我在Scala中这样做:

 var x = BigDecimal(1.1); var y = BigDecimal(0.1); println(x + y); 

我仍然得到一个不精确的结果。

在Scala中有什么我没做的吗?

也许我应该使用Groovy来最大化可读性(它默认使用小数)?

我不知道Scala,但是在Java中, new BigDecimal(1.1)使用double值初始化BigDecimal ,因此它不完全等于1.1。 在Java中,您必须使用new BigDecimal("1.1") 。 也许这对Scala也有帮助。

将您的Scala代码更改为:

 var x = BigDecimal("1.1"); // note the double quotes var y = BigDecimal("0.1"); println(x + y); 

它会像在Java中一样工作。

在这方面,Scala与Java绝对相同。

根据Joachim的回答,编写val x = BigDecimal(1.1)

相当于写作

 val d : Double = 1.1 val x = BigDecimal(d) 

当然,问题在于Double d ALREADY具有舍入误差,因此您使用错误数据初始化x。

使用接受字符串的构造函数,一切都会好的。

根据您的示例,您最好使用val而不是var ,并且您也可以安全地在Scala中保留分号。

您可以在内部将值存储为Integer / String(无精度)并使用scale (这是来自Scala REPL的脚本):

 scala> val Scale = 2 Scale: Int = 2 scala> val x = BigDecimal(110, Scale) x: scala.math.BigDecimal = 1.10 scala> val y = BigDecimal(303, Scale) y: scala.math.BigDecimal = 3.03 scala> (x+y, (x+y).scale) res0: (scala.math.BigDecimal, Int) = (4.13,2) scala> (x*2, (x*2).scale) res1: (scala.math.BigDecimal, Int) = (2.20,2) 

或者,如果要解析字符串,可以控制舍入:

 scala> val z = BigDecimal("8.937").setScale(Scale, BigDecimal.RoundingMode.FLOOR) z: scala.math.BigDecimal = 8.93 scala> val z = BigDecimal("8.937").setScale(Scale, BigDecimal.RoundingMode.CEILING) z: scala.math.BigDecimal = 8.94 
 scala> implicit def str2tbd(str: String) = new { | def toBD = BigDecimal(str) | } str2tbd: (str: String)java.lang.Object{def toBD: scala.math.BigDecimal} scala> var x = "1.1".toBD x: scala.math.BigDecimal = 1.1 scala> var y = "0.1".toBD y: scala.math.BigDecimal = 0.1 scala> x + y res0: scala.math.BigDecimal = 1.2 scala> implicit def str2bd(str: String) = BigDecimal(str) str2bd: (str: String)scala.math.BigDecimal scala> x + y + "1.2345566" res1: scala.math.BigDecimal = 2.4345566 scala> 

我知道这个问题已经过时并且已经回答了,但另一个选择是,如果你对不同的语言开放(就像OP似乎那样),那就是使用Clojure。 Clojure,IMO, BigDecimal数学的一些最简单的语法(注意尾随的M s – 表示BigDecimal ):

 user=> (def x 1.1M) #'user/x user=> (def y 1.1M) #'user/y user=> (def z (* x (.pow y 2))) #'user/z user=> z 1.331M user=> (type z) java.math.BigDecimal 

我喜欢Clojure的数学,因为它在许多情况下默认为精确,例如它使用Ratio

 user=> (/ 60 14) 30/7 user=> (type (/ 60 14)) clojure.lang.Ratio