Javaから、アプリの数学ベースのモジュールのスクリプト言語に切り替えたい。これは、マシーJavaの読みやすさと機能上の制限によるものです。
たとえば、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)
ではBigDecimal
をdouble
値で初期化するため、-ではありません。 正確に 1.1に等しい。Javaでは、代わりにnew BigDecimal("1.1")
を使用する必要があります。多分それはScala as上手。
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
に丸め誤差があるため、xを不正なデータで初期化していることです。
代わりに文字列を受け入れるコンストラクターを使用してください。すべて問題ありません。
あなたの例を考えると、val
sの代わりにvar
sを使用したほうがよいでしょう。また、Scalaでもセミコロンを安全にオフのままにしておくことができます。
値を整数/文字列(精度なし)として内部的に格納し、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
mathの最も単純な構文がいくつかあります(末尾の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