суббота, 2 июня 2012 г.

Вычисления в Java. Math. StrictMath. strictfp.

В стандартной библиотеке языка Java содержатся два класса для произведения базовых математических операций, таких как возведение в степень, взятие логарифма, синуса, косинуса и так далее. Эти классы отличаются между собой различной точностью представления чисел на разных архитектурах процессора. Это классы Math и StrictMath

При использовании StrictMath вы получите абсолютно одинаковый результат вычислений не зависимо от процессора, который установлен у пользователя вашей программы. Прямо говоря, эта функция задумывалась создателями языка как базовая для всех примитивных типов данных и манипуляций с ними. Но как оказалось это не такая простая задача и обеспечение одинаковых результатов на различных платформах значительно уменьшают быстродействие. Большинство задач просто не требуют такой точности в вычислениях, для них гораздо важнее скорость этих вычислений. Это привело к разделению математической части библиотеки на быструю и выдающую одинаковый результат на разных процессорах.

Таким образом если в решении вашей задачи важнее скорость — используйте класс Math, если же вам необходимо одинаковая работа (с точностью до бита) с примитивными типами данных, то ваш выбор — StrictMath. Константы и методы у них одинаковы, и более того некоторые методы класса Math просто вызывают аналогичные методы класса StrictMath.

Рассмотрим не типичные методы этих классов:

  • cbrt — возвращает кубический корень аргумента;
  • ceil — округляет значение в большую сторону;
  • copySign — возвращает первый аргумент со знаком второго;
  • floor — округляет в меньшую сторону;
  • hypot — возвращает квадратный корень из суммы аргументов: sqrt(x2+y2);
  • max — возвращает большее из двух чисел;
  • min — возвращает меньшее из двух чисел;
  • nextAfter — возвращает число с плавающей точкой, максимально приближенной к первому аргументу со стороны второго аргумента;
  • nextUp — то же самое, что и nextAfter, но только всегда в большую сторону;
  • random — возвращает случайное число от 0 до 1;
  • round — обычное округление;
  • signum — возвращает 1.0 если число больше 0 и -1.0 если число меньше нуля и ноль, если аргумент равен нулю;
  • toDegrees — переводит радианы в градусы;
  • toRadians — переводит градусы в радианы;

Пример:
  System.out.println(Math.cbrt(8)); // 2.0
  System.out.println(Math.ceil(2.1)); // 3.0
  System.out.println(Math.copySign(3.4, -11.2)); // -3.4
  System.out.println(Math.floor(9.999)); // 9.0
  System.out.println(Math.hypot(3,4)); // 5.0
  System.out.println(Math.max(3, 2)); // 3
  System.out.println(Math.min(3, 2)); // 2
  System.out.println(Math.nextAfter(4.45634D, -100)); // 4.456339999999999
  System.out.println(Math.nextUp(4.45634D)); // 4.456340000000001
  System.out.println(Math.random()); // 0.45357720245424116
  System.out.println(Math.round(4.5)); // 5
  System.out.println(Math.signum(-34.78)); // -1.0
  System.out.println(Math.toDegrees(Math.PI)); // 180.0
  System.out.println(Math.toRadians(180)); // 3.141592653589793
Остальные методы смотрите в документации: java.lang.Math, jav.lang.StrictMath.

А что нам делать, если мы хотим создать класс, в методах которого все действия с числами будут также гарантированно одинаковые на различных платформах? Или не класс, а метод? В таком случае в языке Java существует ключевое слово strictfp. Его можно добавлять к классу, интерфейсу и методам. Добавив его мы можем быть уверены, что на всех платформах при работе с числами мы получим одинаковый результат.

Комментариев нет:

Отправить комментарий