Почему CLR переполняет Int32.MaxValue -> Single -> Int32, а JVM - нет? - PullRequest
5 голосов
/ 02 ноября 2010

Я столкнулся с неожиданным результатом при циклическом переключении Int32.MaxValue в System.Single:

Int32 i = Int32.MaxValue;
Single s = i;
Int32 c = (Int32)s;

Debug.WriteLine(i); // 2147483647
Debug.WriteLine(c); // -2147483648

Я понял, что это должно быть переполнение, так как Single не имеет достаточно битов взначение и значение Int32, и оно округляется.Когда я изменил conv.r4 на conv.r4.ovf в IL, OverflowExcpetion выбрасывается.Достаточно справедливо ...

Однако, пока я изучал эту проблему, я скомпилировал этот код в java, запустил его и получил следующее:

int i = Integer.MAX_VALUE;
float s = (float)i;
int c = (int)s;

System.out.println(i);  // 2147483647
System.out.println(c);  // 2147483647

Я не знаю много оJVM, но мне интересно, как это происходит.Это кажется гораздо менее удивительным, но как сохранить лишнюю цифру после округления до 2.14748365E9?Сохраняет ли оно какое-то внутреннее представление, а затем заменяет его при приведении к int?Или он просто округляется до Integer.MAX_VALUE, чтобы избежать переполнения?

1 Ответ

3 голосов
/ 02 ноября 2010

Этот случай явно обрабатывается §5.1.3 Спецификации языка Java:

Сужающее преобразование числа с плавающей запятой в целочисленный тип T занимает двашаги:

  1. На первом шаге число с плавающей запятой преобразуется либо в длинное, если T длинное, либо в int, если T байтовое, короткое, char или int,следующим образом:
    • Если число с плавающей запятой равно NaN (§4.2.3), результатом первого шага преобразования будет int или long 0.
    • В противном случае, еслиЧисло с плавающей запятой не является бесконечностью, значение с плавающей запятой округляется до целочисленного значения V, округляя до нуля, используя режим округления до нуля IEEE 754 (§4.2.3).Тогда есть два случая:
      • Если T длинный, и это целочисленное значение может быть представлено как long, то результатом первого шага будет длинное значение V.
      • В противном случае, еслиэто целочисленное значение может быть представлено как int, тогда результатом первого шага будет значение int V.
    • В противном случае один из следующих двух случаев должен быть истинным:
      • Значение должно быть слишком маленьким (отрицательное значение большой величины или отрицательная бесконечность), а результатом первого шага является наименьшее представимое значение типа int или long.
      • Значениедолжно быть слишком большим (положительное значение большой величины или положительная бесконечность), а результатом первого шага является наибольшее представимое значение типа int или long.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...