Я хочу переключиться от 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 для увеличения удобочитаемости (это использует десятичные числа по умолчанию)?
Я не знаю Scala, но в Java новый BigDecimal (1.1)
инициализирует BigDecimal
с помощью двойное
значение и, таким образом, не в точности равно 1,1. В Java вместо этого вы должны использовать new BigDecimal ("1.1")
. Может быть, это поможет и в Scala.
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>
В этом отношении Scala определенно совпадает с Java.
Согласно ответу Иоахима, запись val x = BigDecimal (1.1)
эквивалентна записи
val d : Double = 1.1
val x = BigDecimal(d)
Проблема, конечно, в том, что Double d
УЖЕ имеет округление ошибка, поэтому вы инициализируете x с неверными данными.
Используйте конструктор, который принимает вместо этого строку, и все будет хорошо.
В вашем примере вам также будет лучше использовать val
s вместо var
s, и вы также можете безопасно оставить точку с запятой в Scala.
Вы можете хранить значения как целые числа / строки (без точности) внутри и использовать масштаб
(это расшифровка из 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 на этот:
var x = BigDecimal("1.1"); // note the double quotes
var y = BigDecimal("0.1");
println(x + y);
, и он будет работать так же, как в Java.