Curiosità numeri normali e numeri con virgola

smalldragon
salve a tutti sono un nuovo menbro del forum.

scusatemi per la banalità della domanda che e la seguente:
come si fa a capire se una variabile contiene un numero intero normale o un numero con virgola?
esempio:
x=a/b o x=dato immesso dall'utente
come faccio a capire se x (in ambo i casi) e un numero intero o un numero con virgola?
ringrazio anticipatamente chiunque sia in grado di darmi una risposta.

Risposte
apatriarca
@claudio86: Riguardando i tuoi post, credo ci sia stato una specie di fraintendimento. Parlavamo insomma di cose un po' diverse. Cerco quindi di rendere un po' più chiaro il mio messaggio. Qualsiasi sia la rappresentazione utilizzata, data una successione di \(N\) bit, si possono rappresentare al massimo \(2^N\) valori diversi. Nel caso dei numeri interi senza segno, si rappresentano i numeri naturali minori di \(2^N\). Nel caso dei numeri interi con segno (in cui i numeri negativi sono rappresentati come complemento a due del numero positivo) si rappresentano i numeri interi nell'intervallo \([-2^{N-1}, 2^{N-1} - 1]\). Nel caso dei numeri a virgola mobile, il numero di simboli rappresentabili è sempre \(2^N\), ma l'insieme dal quale questi valori sono stati presi è quello dei numeri razionali (oltre che alcuni simboli aggiuntivi come \(\pm\infty\) e NaN). Inoltre, alcuni valori numerici, come lo zero, hanno più di una rappresentazione: esiste sia lo zero positivo che negativo. A patto quindi di limitarsi ai numeri razionali rappresentabili da un numero floating point, le operazioni di estrazione della parte intera e parte frazionaria sono esatte. Inoltre ci sono molti numeri interi che sono esattamente rappresentabili con questa notazione. Tutti gli interi minori di un certo valore dipendente dalla lunghezza della mantissa per esempio, ma anche alcuni valori molto grandi come \(2^100\) che non sono invece in nessun modo rappresentabili con un intero a 32bit.
E' molto importante saper distinguere tra numeri reali e numeri a virgola mobile. Il numero \(3.000000000000000000000001\) non è uguale a \(3\) se considerato come un numero reale, ma non esiste nei numeri a virgola mobile e se inserito in un computer sarà semplicemente uguale al numero rappresentabile più vicino, che in questo caso è probabilmente \(3\). Ma questo è un problema solo se ci aspettiamo che il computer sia in grado di contenere magicamente ogni numero reale in un numero molto limitato di bit. Se fosse davvero importante saper distinguere tra numeri reali con una tale precisione, allora è necessario fare ricorso a notazioni completamente diverso e a una quantità di memoria potenzialmente molto maggiore (e sarà comunque impossibile rappresentare perfettamente i numeri irrazionali).

claudio862
@apatriarca
Probabilmente hai ragione, non stiamo parlando della stessa cosa.

In questo caso:

float a = 3.0f;

Dentro a c'è il numero intero 3, proprio perché 3 è rappresentabile esattamente in un float (come hai spiegato tu in dettaglio). Quindi posso facilmente verificare senza errori che 3 è intero. Non che sia particolarmente utile, lo sapevo già che 3 è intero.
Più utile potrebbe essere verificare se b è intero:

float b = espressione;

Ma anche se il risultato algebrico di espressione è un intero, quello numerico non è detto (vedi il mio esempio di prima in cui 1/7 + 1/7 + 1/7 + 1/7 + 1/7 + 1/7 + 1/7 /= 1), potrebbe esserci un errore. Nella maggior parte dei casi (non in tutti) sarà abbastanza piccolo da poter essere tralasciato, ma in generale non puoi fare

if (modf(b, & c) == 0.0f)
    // Intero


Quello che volevo dire è che si può sapere se il risultato di un algoritmo (o un'espressione) è intero solo con una certa approssimazione. Al limite si potrebbero usare librerie per il calcolo in $\mathbb{Q}$, che permettono precisione infinita (a scapito di memoria e velocità).

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