Types en Scala, Long, Int, etc.

Saisissez ceci.

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

Que se passe-t-il ici? J'ai fait du parachutisme et je dois dire que c'est la chose la plus dangereuse que j'ai jamais vue. Pas de vérification du compilateur pour cela? Évidemment, si je substituais 150 à une variable différente.

* modifier *

C'était le code réel qui m'a inquiété.

val oneDay = 86400000
val days150 = oneDay * 150

days150 = 75098112

Ce n'était pas la faute de Scala ou de n'importe qui sauf la mienne. Viens m'inquiète.

26
demandé sur Drew H 2011-12-20 21:47:42

2 réponses

Il n'y a rien de spécifique à Scala à ce sujet. Il s'agit simplement du type cible de l'affectation qui n'est pas pertinent par rapport au type dans lequel une opération (multiplication dans ce cas) est effectuée.

Par exemple, en 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
    }
}

La partie unchecked ici est parce que le compilateur C# est assez intelligent pour réaliser que l'opération déborde, mais seulement parce que les deux opérandes sont des constantes. Si l'un ou l'autre opérande avait été une variable, cela aurait été bien sans unchecked.

De même en 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
    }
}
15
répondu Jon Skeet 2011-12-20 17:49:25

Il est évident qu'il n'y a pas de casting implicite. 86400000 * 150 est considéré comme int * int par j'imagine que la jvm. Il est calculé puis assigné à n'importe quelle variable de type U désir qui ne fait aucune différence. Donc, la bonne chose à faire est de s'assurer qu'au moins un des nombres ou des variables est converti en type long, 86400000 * 150.toLong . La jvm semble par défaut au type plus grand.

Btw, je crois qu'un contrôle de débordement sur la fin de scala ne ferait que paralyser les performances. Donc l'omission de la conversion de type automatique introduit le risque mais permet une meilleure performance. Vous avez juste à être prudent ... qui devrait être une seconde nature si vous venez d'un c/c++ de sauvegarde.

0
répondu 2015-11-11 20:11:40