f64::mul_add în Rust

Calculează (x * a) + b cu o singură rotunjire la final (fused multiply-add), deci mai precis.

Sintaxă
fn mul_add(self, a: f64, b: f64) -> f64   // (self * a) + b

Ce face f64::mul_add

x.mul_add(a, b) calculează x * a + b. Diferența față de scrierea obișnuită este că rezultatul intermediar x * a nu mai este rotunjit: se rotunjește o singură dată, la final. Rezultatul este mai precis, iar pe procesoarele cu instrucțiune FMA (aproape toate cele moderne) este și rapid.

Se folosește la evaluarea polinoamelor (metoda lui Horner), la produse scalare și în calcule științifice. Atenție: pe procesoare fără FMA, operația este emulată în software și poate fi mult mai lentă.

Parametri

Parametru Descriere
a Factorul cu care se înmulțește self.
b Termenul adunat la produs.

Ce returnează

f64.

Exemple

Exemplul 1: O rotunjire în loc de două

0.1 nu este exact 0.1 în binar. Cu două rotunjiri eroarea dispare (din întâmplare), cu una singură rămâne vizibilă diferența reală.

fn main() {
    let x = 0.1_f64;
    println!("x * 10 - 1      = {:e}", x * 10.0 - 1.0);
    println!("x.mul_add(10,-1) = {:e}", x.mul_add(10.0, -1.0));
    println!("2.mul_add(3, 1)  = {}", 2.0_f64.mul_add(3.0, 1.0));
}

Rezultat

x * 10 - 1      = 0e0
x.mul_add(10,-1) = 5.551115123125783e-17
2.mul_add(3, 1)  = 7

Exemplul 2: Evaluarea unui polinom cu metoda lui Horner

Pentru p(x) = 2x³ - 3x² + 0.5x + 7, fiecare pas este rezultat * x + coeficient.

fn polinom(coeficienti: &[f64], x: f64) -> f64 {
    coeficienti.iter().fold(0.0, |acc, &c| acc.mul_add(x, c))
}

fn main() {
    let p = [2.0, -3.0, 0.5, 7.0];
    for x in [0.0, 1.0, 2.5, -1.0] {
        println!("p({x}) = {}", polinom(&p, x));
    }
}

Rezultat

p(0) = 7
p(1) = 6.5
p(2.5) = 20.75
p(-1) = 1.5

Greșeli frecvente

  • Te aștepți ca mul_add să dea exact același rezultat ca x * a + b: poate diferi în ultimele zecimale (este mai precis).
  • Folosești mul_add peste tot pentru viteză, pe un procesor fără FMA: devine mai lent.

Comenzi înrudite

  • f64::powi: powi ridică la o putere întreagă (poate fi negativă), powf la o putere cu zecimale.
  • f64: Tipul implicit pentru numere cu zecimale: virgulă mobilă pe 64 de biți (precizie dublă, IEEE 754).
  • f64::to_radians: to_radians transformă grade în radiani; sin, cos și tan primesc unghiul în radiani.