Типы в Scala, Long, Int и т. Д. - PullRequest
       15

Типы в Scala, Long, Int и т. Д.

30 голосов
/ 20 декабря 2011

Пожалуйста, введите это.

scala> 86400000 * 150
res0: Int = 75098112


scala> val i : Long = 86400000 * 150
i: Long = 75098112  


val i  = 86400000 * 150.asInstanceOf[Long]
i: Long = 12960000000

val i  = 86400000 * 150L
i: Long = 12960000000

Что здесь происходит в мире?Я прыгал с парашютом и должен сказать, что это самая опасная вещь, которую я когда-либо видел.Нет проверки компилятора для этого?Очевидно, если бы я подставил 150 для переменной, которая отличается.

* РЕДАКТИРОВАТЬ *

Это был фактический код, который меня беспокоил.

val oneDay = 86400000
val days150 = oneDay * 150

days150 = 75098112

Это была не ошибка Скалы или чья-либо ошибка, кроме моей.Просто волновал меня.

Ответы [ 2 ]

15 голосов
/ 20 декабря 2011

В этом нет ничего специфичного для Scala. Это просто вопрос того, что целевой тип присваивания не имеет отношения к типу, в котором выполняется операция (в данном случае умножение).

Например, в C #:

using System;

class Program
{
    static void Main(string[] args)
    {
        int a = unchecked(86400000 * 150);
        long b = unchecked(86400000 * 150);
        long c = 86400000 * (long) 150;
        long d = 86400000 * 150L;
        Console.WriteLine(a); // 75098112
        Console.WriteLine(b); // 75098112
        Console.WriteLine(c); // 12960000000
        Console.WriteLine(d); // 12960000000
    }
}

Часть unchecked здесь заключается в том, что компилятор C # достаточно умен, чтобы понять, что операция переполнена, но только потому, что оба операнда являются константами. Если бы любой операнд был переменной, все было бы хорошо без unchecked.

Аналогично в Java:

public class Program
{
    public static void main(String[] args)
    {
        int a = 86400000 * 150;
        long b = 86400000 * 150;
        long c = 86400000 * (long) 150;
        long d = 86400000 * 150L;
        System.out.println(a); // 75098112
        System.out.println(b); // 75098112
        System.out.println(c); // 12960000000
        System.out.println(d); // 12960000000
    }
}
0 голосов
/ 11 ноября 2015

Очевидно, что не происходит никакого неявного приведения. 86400000 * 150 рассматривается как int * int Я представляю JVM. Затем он вычисляется для любой переменной, которая вам не нужна. Поэтому правильно сделать так, чтобы по крайней мере одно из чисел или переменных было приведено к типу long, 86400000 * 150.toLong. По умолчанию jvm имеет больший тип.

Кстати, я полагаю, что проверка переполнения на конце scala только снизит производительность. Таким образом, отсутствие автоматического преобразования типов создает риск, но позволяет повысить производительность. Вы просто должны быть осторожны ... что должно быть второй натурой, если вы пришли из резервной копии c / c ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...