Scala и Java BigDecimal

Я хочу переключиться от 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, простые формулы являются сложными реальные быстрый.

С удваивается, это выглядит хорошо, но мне нужна точность.

Я надеялся в 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 для увеличения удобочитаемости (это использует десятичные числа по умолчанию)?

28
задан Jonas 20 June 2011 в 18:30
поделиться

5 ответов

Я не знаю Scala, но в Java новый BigDecimal (1.1) инициализирует BigDecimal с помощью двойное значение и, таким образом, не в точности равно 1,1. В Java вместо этого вы должны использовать new BigDecimal ("1.1") . Может быть, это поможет и в Scala.

38
ответ дан 28 November 2019 в 02:22
поделиться
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>
5
ответ дан 28 November 2019 в 02:22
поделиться

В этом отношении Scala определенно совпадает с Java.

Согласно ответу Иоахима, запись val x = BigDecimal (1.1)

эквивалентна записи

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

Проблема, конечно, в том, что Double d УЖЕ имеет округление ошибка, поэтому вы инициализируете x с неверными данными.

Используйте конструктор, который принимает вместо этого строку, и все будет хорошо.

В вашем примере вам также будет лучше использовать val s вместо var s, и вы также можете безопасно оставить точку с запятой в Scala.

13
ответ дан 28 November 2019 в 02:22
поделиться

Вы можете хранить значения как целые числа / строки (без точности) внутри и использовать масштаб (это расшифровка из 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
6
ответ дан 28 November 2019 в 02:22
поделиться

Измените свой код Scala на этот:

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

, и он будет работать так же, как в Java.

31
ответ дан 28 November 2019 в 02:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: