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.
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
}
}
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.