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