Подтвердить что ты не робот

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

Введите это.

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 для переменной, которая бы отличалась.

* EDIT *

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

val oneDay = 86400000
val days150 = oneDay * 150

days150 = 75098112

Это не ошибка Scala или любая ошибка, кроме моей. Меня только что беспокоило.

4b9b3361

Ответ 1

Там ничего Scala -специфично. Это просто вопрос целевого типа назначения, не относящегося к типу, в котором выполняется операция (умножение в этом случае).

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

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 здесь объясняется тем, что компилятор С# достаточно умен, чтобы понять, что операция переполняется, но только потому, что оба операнда являются константами. Если бы один из операндов был переменной, это было бы прекрасно без 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
    }
}

Ответ 2

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

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