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

#java #newtons-method

#java #метод ньютонов

Вопрос:

Это мой код для школьного задания. Я должен был создать код, который мог бы вычислить квадратный корень из любого числа, используя метод Ньютона и начиная угадывать. Он работал правильно, когда эпсилон был равен 0,0001, однако меня попросили сделать его более точным. При изменении на 0.00000001 (запрошенный моим учителем) он бесконечно повторяется, потому что он неоднократно выдает ответ, который не превышает 0.00000001 целевого числа при умножении на себя, и все дальнейшие вычисления дают тот же результат.

 import java.lang.Math.*;

public class main {
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("Enter the number you are trying to find the square root of");
    Float input1 = sc.nextFloat();
    Scanner sc2 = new Scanner(System.in);
    System.out.println("Provide a guess to start");
    Float input2 = sc2.nextFloat();
    calc(input1, input2);
    }
    static void calc(Float input1, Float input2) {
       final double epsilon = 0.00000001; 
        float sqr = (input1/input2   input2)/2;
        do{
        sqr = (input1/input2   input2)/2;
        input2 = sqr;
        } while (Math.abs(sqr * sqr - input1)>epsilon);
        System.out.println("The square root of "   input1   " is "   sqr);
        
    }}
 

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

1. float для этого недостаточно точности. Используйте double .

2. В качестве отступления: здесь нет необходимости использовать Float : вместо этого используйте float (или, как предложено double ).

Ответ №1:

Числа с плавающей запятой имеют ограниченную точность.

Важным понятием является единица наименьшей точности, или ULP. Это величина, на которую изменяется число, если вы меняете его младший значащий бит.

Это меняется в зависимости от числа, с которого вы начинаете; но для 1.0f ULP 1.1920929E-7 . (Вы можете найти это с помощью Math.ulp метода). Итак, предполагая, что вы пытаетесь найти что-то лучшее решение из чего-то порядка 1, используя float , вы не можете получить в пределах 1e-8 от него.

Используйте double вместо этого: у вас все еще ограниченная точность, но ULP намного меньше: 2.2e-16.

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

1. А для всего остального есть BigDecimal и слезы.