Math.fma în Java

Calculează a × b + c cu o singură rotunjire la final (fused multiply-add), mai precis decât a * b + c.

Sintaxă
static double fma(double a, double b, double c)   // și float

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 fma să rezolve problemele lui 0.1 + 0.2: nu, valorile double rămân aproximative; fma elimină 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.