Precisione della matematica.sin () in Java per angoli comuni


Ho due metodi per calcolare la derivata di sin (pi), è per uni-uno usa la formula di differenziazione numerica comune, l'altro ho riscritto come segue:

// h = 1e−16 (part of assignment)
// f'(x) ~= (f(x+h)-f(x))/h  for sin(x)
public static double differentiateSin(double x) {
    return (Math.sin(x+h)-Math.sin(x))/h;
}

// using trigonometry
public static double differentiateSin2(double x) {
    return (2* ( Math.sin(h/2) * Math.cos(x+h/2) ) )  /h;
}

Sono consapevole che i numeri in virgola mobile non possono essere rappresentati esattamente, molto meno pi, quello che mi sorprende è che sto ottenendo un risultato abbastanza esatto con il secondo metodo, mentre il primo è completamente fuori pista!

Matematica (cos (Matematica.pi)) dà un esatto -1.0, immagino che vada bene, è un angolo comune - ma io non riesco a capire cosa faccia una tale differenza tra questi metodi. Ci sono altre operazioni, non mi sono liberato del peccato e del cos, eppure sto ottenendo risultati perfetti.

Anche rendere 'h' più grande dà risultati più ragionevoli... Cosa succede lì?

Author: kacerekz, 2018-03-26