Math.sqrt: примеры (JAVA)

Использование sqrt в Java
Раздел: Математические операции
Math.sqrt(double a): double

Описание Math.sqrt

Метод Math.sqrt(double a) в Java вычисляет квадратный корень из числа типа double. Подпись метода: public static double sqrt(double a). Метод принадлежит классу java.lang.Math и является статическим.

Когда применяется

Применяется при вычислении положительного квадратного корня действительного числа, при обработке геометрических и статистических вычислений, при решении задач с расстояниями, нормализацией и т.д.

Аргументы и возвращаемые значения

  • a - аргумент типа double.
  • Возвращаемое значение - double, равное положительному квадратному корню из a, либо специальное значение в особых случаях.

Особые случаи поведения

  • Если a равен положительной бесконечности (Double.POSITIVE_INFINITY), возвращается положительная бесконечность.
  • Если a равно Double.NaN, возвращается Double.NaN.
  • Если a меньше нуля и не является отрицательным нулем, возвращается Double.NaN (не генерируется исключение).
  • Если a равен +0.0, возвращается +0.0; если a равен -0.0, возвращается -0.0 согласно стандарту IEEE 754.

Замечания по точности

Метод Math.sqrt реализует эффективную реализацию, оптимизированную в JVM. Для гарантированно корректного округления и платформозависимой воспроизводимости существует аналог StrictMath.sqrt, у которого поведение согласовано между реализациями JVM.

Короткие примеры использования

Ниже несколько простых примеров с кодом и результатом.

Положительное число

public class Main {
    public static void main(String[] args) {
        double v = Math.sqrt(16.0);
        System.out.println(v);
    }
}
4.0

Ноль и отрицательный ноль

public class Main {
    public static void main(String[] args) {
        System.out.println(Math.sqrt(0.0));   // +0.0
        System.out.println(Math.sqrt(-0.0));  // -0.0
    }
}
0.0
-0.0

Отрицательное значение

public class Main {
    public static void main(String[] args) {
        System.out.println(Math.sqrt(-4.0));
    }
}
NaN

Специальные значения

public class Main {
    public static void main(String[] args) {
        System.out.println(Math.sqrt(Double.POSITIVE_INFINITY));
        System.out.println(Math.sqrt(Double.NaN));
    }
}
Infinity
NaN

Похожие методы в Java

В Java имеются методы и подходы, близкие по назначению.

  • StrictMath.sqrt - поведение согласовано между JVM, предпочтение при необходимости платформонезависимого, детерминированного округления.
  • Math.pow(x, 0.5) - альтернативный способ вычисления корня, но обычно медленнее и менее явен в намерении кода.
  • Math.hypot(x, y) - вычисляет sqrt(x*x + y*y) безопасно с защитой от переполнения и потери точности; подходит при работе с длинами вектора.
  • BigDecimal (через пользовательские алгоритмы) - применяется при необходимости высокой точности результата; требуется собственная реализация метода извлечения корня.

Выбор между ними зависит от требований к точности, портируемости и производительности. Для простых вычислений Math.sqrt обычно достаточно. Для воспроизводимости между JVM предпочтительнее StrictMath.sqrt. Для безопасного вычисления гипотенузы лучше Math.hypot. Для высокой десятичной точности - алгоритмы на BigDecimal.

Аналоги в других языках и особенности

Короткие сравнения по языкам с примерами.

  • JavaScript: Math.sqrt(x). Для отрицательных аргументов возвращается NaN.
// JavaScript
console.log(Math.sqrt(9));
console.log(Math.sqrt(-1));
3
NaN
  • Python: math.sqrt(x) - при отрицательном аргументе возникает исключение ValueError. Для комплексных значений используется cmath.sqrt.
# Python
import math
print(math.sqrt(9))
# math.sqrt(-1)  # ValueError: math domain error
import cmath
print(cmath.sqrt(-1))
3.0
1j
  • PHP: sqrt($x) возвращает NaN для отрицательных значений в режиме float.
<?
echo sqrt(9)."\n";
echo sqrt(-1)."\n"; // NAN
?>
3
NAN
  • C#: Math.Sqrt(double), поведение похоже на Java: возвращает Double.NaN для отрицательных аргументов.
// C#
using System;
class P{static void Main(){
    Console.WriteLine(Math.Sqrt(9));
    Console.WriteLine(Math.Sqrt(-1));
}}
3
NaN
  • Go: math.Sqrt(x) из пакета math, поведение аналогично возвращению NaN для отрицательных.
// Go
package main
import ("fmt"; "math")
func main(){
    fmt.Println(math.Sqrt(9))
    fmt.Println(math.Sqrt(-1))
}
3
NaN
  • Lua: math.sqrt(x), для отрицательных может вернуться nan в зависимости от платформы.

SQL

Во многих СУБД есть функция SQRT(x). Поведение при отрицательных значениях зависит от СУБД: возможен возврат NaN, NULL или ошибка. Рекомендуется проверять документацию конкретной СУБД.

Отличия от Java

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

Типичные ошибки при использовании

  • Ожидание исключения при отрицательном аргументе. В Java возвращается NaN, а не исключение. Пример:
public class Main {
    public static void main(String[] args) {
        double r = Math.sqrt(-9.0);
        System.out.println(r);
        System.out.println(Double.isNaN(r));
    }
}
NaN
true
  • Использование Math.sqrt для целых типов без приведения и неучет дробной части. Пример:
public class Main {
    public static void main(String[] args) {
        int a = 2;
        int r = (int)Math.sqrt(a * a + 1); // приведение обрезает дробную часть
        System.out.println(r);
    }
}
2
  • Ручное вычисление гипотенузы через Math.sqrt(x*x + y*y) без учета переполнения и потери точности. В таких случаях возможна неправильная оценка. Рекомендуется Math.hypot:
// проблема при больших значениях
public class Main {
    public static void main(String[] args) {
        double x = 1e308;
        double y = 1e308;
        System.out.println(Math.sqrt(x*x + y*y)); // может дать Infinity или неверный результат
        System.out.println(Math.hypot(x, y));      // безопаснее
    }
}
Infinity
Infinity
  • Ожидание точно округленного результата для финансовых вычислений. Для таких задач BigDecimal и специальные алгоритмы точнее.

Изменения в последних версиях Java

API Math.sqrt не претерпевал значительных изменений в семантике. Основные изменения, заметные пользователю, связаны с внутренними оптимизациями JVM: современные версии JIT могут заменять вызов на аппаратную инструкцию процессора для повышения производительности. Для строго детерминированного поведения остается StrictMath.sqrt. В новых релизах улучшалась производительность и соответствие стандартам IEEE 754 без изменения спецификации метода.

Расширенные и редкие случаи использования

Безопасный алгоритм извлечения корня для BigDecimal

Приведен пример реализации квадратного корня для BigDecimal на основе метода Ньютона. Используется при необходимости высокой десятичной точности.

Пример java
import java.math.BigDecimal;
import java.math.MathContext;

public class BigDecimalSqrt {
    public static BigDecimal sqrt(BigDecimal value, MathContext mc) {
        BigDecimal x = new BigDecimal(Math.sqrt(value.doubleValue()), mc);
        BigDecimal two = BigDecimal.valueOf(2);
        for (int i = 0; i < mc.getPrecision(); i++) {
            x = x.add(value.divide(x, mc)).divide(two, mc);
        }
        return x;
    }

    public static void main(String[] args) {
        BigDecimal v = new BigDecimal("2");
        System.out.println(sqrt(v, new MathContext(20)));
    }
}
1.4142135623730950488

Использование Math.hypot для точной длины вектора

Пример java
public class HypotExample {
    public static void main(String[] args) {
        double x = 3e200;
        double y = 4e200;
        System.out.println("manual: " + Math.sqrt(x*x + y*y));
        System.out.println("hypot:   " + Math.hypot(x, y));
    }
}
manual: Infinity
hypot:   5.0E200

Квадратный корень в решении квадратного уравнения

Пример java
public class Quadratic {
    public static void main(String[] args) {
        double a = 1, b = 0, c = 1; // x^2 + 1 = 0
        double d = b*b - 4*a*c;    // дискриминант
        System.out.println("discriminant: " + d);
        System.out.println("sqrt(discriminant): " + Math.sqrt(d)); // NaN
    }
}
discriminant: -4.0
sqrt(discriminant): NaN

Работа с комплексными числами через библиотеки

Для комплексных корней используется сторонняя библиотека, например Apache Commons Math. Пример со сложением и извлечением корня приведен без кода библиотеки, но принцип: использовать класс Complex и его метод sqrt().

Параллельная обработка массивов

Пример java
import java.util.Arrays;

public class ParallelSqrt {
    public static void main(String[] args) {
        double[] arr = {1,4,9,16,25};
        Arrays.parallelSetAll(arr, i -> Math.sqrt(arr[i]));
        for (double v : arr) System.out.println(v);
    }
}
1.0
2.0
3.0
4.0
5.0

Нестандартный случай: проверка на отрицательный ноль

Пример java
public class NegZero {
    public static void main(String[] args) {
        double nz = -0.0;
        double r = Math.sqrt(nz);
        System.out.println(r == 0.0); // true
        System.out.println(Double.doubleToRawLongBits(r)); // битовое представление сохраняет знак
    }
}
true
9223372036854775808

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

джава Math.sqrt function comments

En
Math.sqrt Квадратный корень