math.FMA în Go

Calculează x*y + z cu o singură rotunjire la final (fused multiply-add), mai precis decât cele două operații separate.

Sintaxă
import "math"

func FMA(x, y, z float64) float64

Ce face math.FMA

math.FMA(x, y, z) calculează x*y + z ca și cum produsul ar avea precizie infinită și rotunjește o singură dată, la final. Expresia obișnuită rotunjește de două ori: după înmulțire și după adunare.

Diferența este mică, dar contează în calcule numerice care adună multe produse (polinoame, produse scalare). Pe procesoarele moderne FMA este și o singură instrucțiune rapidă.

Compilatorul Go poate combina singur x*y + z într-un FMA pe unele procesoare (de exemplu ARM64). O conversie explicită, float64(x*y) + z, forțează rotunjirea produsului. math.FMA garantează mereu rotunjirea unică.

Parametri

Parametru Descriere
x, y, z Factorii înmulțiți (x, y) și termenul adunat (z).

Ce returnează

Rezultatul x*y + z rotunjit o singură dată.

Exemple

Exemplul 1: Diferența față de două rotunjiri

0.1 nu se poate memora exact. Produsul 0.1 * 10 rotunjit dă exact 1, deci diferența pare 0. FMA păstrează eroarea mică a produsului și o arată.

package main

import (
    "fmt"
    "math"
)

func main() {
    x, y, z := 0.1, 10.0, -1.0
    fmt.Println(float64(x*y) + z)
    fmt.Println(math.FMA(x, y, z))
}

Rezultat

0
5.551115123125783e-17

Exemplul 2: Evaluarea unui polinom (schema lui Horner)

p(x) = 2x³ − 3x² + x − 5, calculat ca ((2x − 3)x + 1)x − 5, cu câte un FMA pe pas.

package main

import (
    "fmt"
    "math"
)

func main() {
    coef := []float64{2, -3, 1, -5}
    x := 1.5
    r := 0.0
    for _, c := range coef {
        r = math.FMA(r, x, c)
    }
    fmt.Println("p(1.5) =", r)
}

Rezultat

p(1.5) = -3.5

Greșeli frecvente

  • Te aștepți ca x*y + z să dea același rezultat pe toate procesoarele: compilatorul poate folosi FMA pe unele și nu pe altele. Dacă rezultatul trebuie să fie identic, folosește explicit math.FMA sau conversia float64(x*y).

Comenzi înrudite

  • math.Pow: math.Pow ridică x la puterea y, iar math.Pow10 calculează 10 la puterea n.
  • math.Nextafter: Returnează următorul număr reprezentabil după x, în direcția lui y (float64 sau float32).