Precisione di macchina e matlab

Galager
Ciao a tutti, studiando la precisione di macchina ho trovato un contrasto tra teoria e pratica che non capisco.
L'ambiente sono i numeri di macchina $F(\beta,t,m,M)$.
Una delle definizioni di precisione di macchina è la seguente: 'il minimo numero che sommato (in aritmetica di macchina) a 1 non fa 1; inoltre il suo valore è $1/2*\beta^(1-t)$.
ora usando matlab ho notato che
1. 1+eps=1 (e non >1 come è stato dimostrato sulla teoria)
2. provando a isolare t ho trovato $t=16.3525$, ma t non è supposto essere essere intero?
3. non ho ben capito se quando si parla di 'minimo numero' si intenda in valore assoluto oppure no. Ma usando sia $a=2e-16$ sia $b=3e-16$ si ottiene $1+=1$ e $1+b=b$.

Le operazioni sono state fatte in format long. Spero possiate aiutarmi, grazie!!

Risposte
feddy
i) Quella definizione non è proprio la migliore. Una migliore è che $\epsilon$ è la distanza tra $1$ ed il successivo numero in virgola mobile. In MatLab [inline]1+eps>1[/inline] da come risultato [inline]1[/inline] cioè true.


ii) Non ha molto senso ricavarsi $t$ a ritroso. In ogni caso, deve essere intero, per come è definito

iii) Per come è definito, essendo la base $\beta >0$, è inteso positivo.

Galager
OK grazie. perchè non ha senso calcolarsi t a ritroso? (in effetti 1+abs==1 è false, ma comunque calcolando 1+abs esce 1, come mai?)

feddy
Perché vengono visualizzate solamente le prime 16 cifre decimali. Ma, per costruzione, quel numero sarà più grande di 1. Prova a stampare a video [inline]1+1e-15[/inline]. Troverai un 1 nell'ultima cifra che vedi nel terminale. D'altronde, l'unità di roundoff è dell'ordine di $10^(-16)$, ecco perché non noti la differenza, che però c'è.

feddy
Ti propongo un fatto carino, che spero possa essere utile per farti comprendere quanto bisogna stare attenti talvolta all'aritmetica floating point.


Calcola $\log(1+x)$ per $x$ molto piccolo.


Per un $x> -1$ tale che $|x|< \mu$, dove $\mu$ è l'unita di roundoff, hai che necessariamente [inline]1+x == 1[/inline]. Perciò $\log(1+x)=\log(1)=0$: che è clamorosamente errato. Infatti, per $x = 10^(-18)$, hai che $\log(1+x) \approx 10^(-18)$ in aritmetica esatta, non $0$ come invece trovi sul tuo pc! L'errore relativo infatti è molto grande $E_r(x)\approx\frac{10^(-18)-0}{10^(-18)} = 1$.


Come ovviare a questo inconveniente? Usando Taylor con resto di Lagrange in un intorno di $x$ abbiamo

$\log(1+x)=x-\frac{x^2}{2} + \mathcal{O}(x^3/3)$

Perciò l'errore commesso è dell'ordine di $\frac{x^3}{3}$. Pertanto, per valori $|x|<10^{-4}$ trovi che $\log(1+x)$ viene valutata con un errore $|E(x)| < 10^{-12}$. Questo breve listato in C++ ti permette di fare diversi test:

#include <iostream>
#include <cmath>


struct NonAccett{
    std::string messaggio;
    NonAccett(std::string s): messaggio{std::move(s)} {}
    const char* what() const {return messaggio.c_str();}
};


double log1px(const double& x){
    
    if (x<=-1) {
        throw NonAccett(std::to_string(x) + " è minore di -1, non accettabile");
    }
    
    if (std::fabs(x)>1e-4) {
        return log(1+x); //non ci sono grandi problemi di accuratezza
    }
    
    return x*(1 - 0.5*x);
    
}


int main(){
    
    const double x{1e-15};
    try {
        double test{log1px(x)};
        std::cout << test << std::endl;
        return 0;

    } catch (const NonAccett& tp) {
        std::cout << tp.what() <<std::endl;
        return 1;
    }
    
}

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.