Ce face Math.fma
La a * b + c, Java rotunjește rezultatul înmulțirii, apoi rotunjește din nou după adunare. Math.fma(a, b, c) (fused multiply-add) calculează expresia ca și cum ar avea precizie infinită și rotunjește o singură dată, la sfârșit.
Diferența apare rar, dar contează în calcule numerice sensibile: produse scalare, evaluarea polinoamelor (schema lui Horner), algoritmi care compensează erorile de rotunjire. Pe procesoarele moderne, fma este o instrucțiune hardware și este rapidă.
Parametri
| Parametru | Descriere |
|---|---|
a, b |
Factorii înmulțirii. |
c |
Termenul adunat. |
Ce returnează
a × b + c, rotunjit o singură dată.
Exemple
Exemplul 1: Eroarea ascunsă de rotunjire
Produsul 0.1 × 10 este rotunjit la exact 1.0, deci a * b - 1 dă 0. fma arată diferența reală dintre 0.1 (stocat aproximativ) × 10 și 1.
public class Main {
public static void main(String[] args) {
double a = 0.1;
double b = 10;
System.out.println(a * b - 1);
System.out.println(Math.fma(a, b, -1));
}
}
Rezultat
0.0
5.551115123125783E-17
Exemplul 2: Evaluarea unui polinom
Calculăm 2x³ − 3x² + x − 5 pentru x = 1.5 cu schema lui Horner.
public class Main {
public static void main(String[] args) {
double[] coeficienti = {2, -3, 1, -5};
double x = 1.5;
double rezultat = 0;
for (double c : coeficienti) {
rezultat = Math.fma(rezultat, x, c);
}
System.out.println(rezultat);
}
}
Rezultat
-3.5
Greșeli frecvente
- Te aștepți ca
fmasă rezolve problemele lui0.1 + 0.2: nu, valoriledoublerămân aproximative;fmaelimină doar o rotunjire intermediară.
Comenzi înrudite
Math.IEEEremainder: Restul împărțirii după standardul IEEE 754: f1 − f2 × n, unde n este câtul rotunjit la cel mai apropiat întreg.Math.nextUp: Lucrează cu „pașii” dintre numerele double: valoarea imediat următoare sau anterioară și mărimea pasului (ulp).Math: Clasa cu funcții matematice gata făcute: rotunjiri, puteri, radicali, trigonometrie, minim/maxim și calcule întregi sigure.