31

アプリの Math ベースのモジュールを Java からスクリプト言語に切り替えたいと考えています。これは、mathy Java の読みやすさと機能上の制限によるものです。

たとえば、Javaではこれがあります:

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

ご覧のとおり、BigDecimal 演算子のオーバーロードがなければ、単純な数式がすぐに複雑になります。

double の場合、これは問題ないように見えますが、精度が必要です。

私は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 を使用して読みやすさを最大化する必要があります (デフォルトでは小数を使用します)。

4

6 に答える 6

39

Scala はわかりませんが、Java ではを値でnew BigDecimal(1.1)初期化するため、1.1 と正確には等しくありません。Javaでは、代わりに使用する必要があります。多分それはScalaでも役立つでしょう。BigDecimaldoublenew BigDecimal("1.1")

于 2010-04-23T10:01:48.243 に答える
35

Scala コードを次のように変更します。

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

Java と同じように機能します。

于 2010-04-23T10:04:51.943 に答える
13

この点では、Scala は間違いなく Java と同じです。

ヨアヒムの答えによると、書き込みval x = BigDecimal(1.1)

書くことに等しい

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

もちろん、問題は Double dALREADY に丸め誤差があるため、 x を不良データで初期化していることです。

代わりに文字列を受け入れるコンストラクターを使用すると、すべて問題ありません。

あなたの例を考えると、vals の代わりにvars を使用する方が良いでしょう.Scalaでもセミコロンを安全に残すことができます.

于 2010-04-23T11:12:38.800 に答える
7

値を整数/文字列 (精度なし) として内部に格納し、使用することができます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
于 2010-04-23T13:15:32.970 に答える
6
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>
于 2010-04-23T10:28:35.733 に答える
2

私はこの質問が古くて答えられていることを知っていますが、(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
于 2011-06-06T13:56:04.973 に答える