Math.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 на основе метода Ньютона. Используется при необходимости высокой десятичной точности.
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 для точной длины вектора
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
Квадратный корень в решении квадратного уравнения
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().
Параллельная обработка массивов
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
Нестандартный случай: проверка на отрицательный ноль
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
Значение битового представления показывает сохранение знака нуля в результате.