пятница, 22 июля 2016 г.

Переполнение

В процессе написания своих прозрачных скроллбаров для IDEA я наступил на классические грабли.

Для преобразования целого числа [1..100] в целое число [1..10] надо ( value * 10 / 100 ), причём сначала умножить, чтобы точность не потерять. Это известная целочисленная арифметика.

Но в целочисленной арифметике есть проблема переполнения, с которой и столкнулись люди на чрезвычайно длинных файлах. Например, если миллион умножить на две тысячи, то получим 2 000 000 000, а если на три, то получим -1 294 967 296.

7 комментариев:

  1. Вот этой фразы
    > Для преобразования целого числа [1..100] в целое число [1..10] надо ( value * 10 / 100 ), причём сначала умножить, чтобы точность не потерять
    я, честно говоря, не понял.

    ОтветитьУдалить
    Ответы
    1. Ну... есть числа из одного диапазона (значение позиции скроллбара в условных единицах), которые нужно преобразовать к другому диапазону (пиксели). Если поделить 44 на 100, а потом умножить на 10, то получишь 0, а не 4.

      Удалить
    2. А что сразу на 10 не поделить?

      Удалить
  2. Десяти нет. Ложки нет :)
    Есть первый диапазон и второй. И числа могут быть разные, не делящиеся друг на друга.

    ОтветитьУдалить
    Ответы
    1. А, ок. Туплю после отпуска :)

      Вообще, это стандартная задача нормализации числа - не только целого - в машинной арифметике. Помнится, на моей 42-й кафедре очень любили задачки на эту тему. Javа не умеет сообщать, что случилось overflow (или underflow)? Так-то это вполне машинно-зависимый код, но в принципе несложно обойти и так.

      Удалить
    2. Вот тебе в тему: https://twitter.com/chvest/status/744129999934996480

      Удалить
    3. Не. Java кладёт на переполнение

      Удалить