Oppure

Loading
26/05/14 9:02
Roby, come fai a determinare se un numero è un intero a partire da un valore in virgola mobile? Ho provato con modf(), controllando se la parte decimale è uguale a zero, ma praticamente non lo è mai perché in fondo al numero c'è sempre qualche decimale "incontrollato" che rende inaffidabile il confronto con 0.0

bool Intero( double val ) {  // questa non funziona!
    double parte_intera, parte_decimale;
    parte_decimale = modf( val, &parte_intera );
    return parte_decimale == 0.0;
}


Suggerimenti a prova di idiota? C'è qualche funzione di libreria che mi è sfuggita e che si occupa di verificare se un numero in virgola mobile è o non è un intero? (mi sembra contraddittorio: se è in virgola mobile non è un intero... anche se è un intero!) Cosa mi sfugge?
Ultima modifica effettuata da 26/05/14 9:03
26/05/14 11:29
Roby94
Intero ovviamente va visto in senso matematico del termine, non in senso informatico.
Questa funzione è molto legata al linguaggio scelto, la più versatile di tutte mi sembra questa:
function IsIntegerNumber(double d) {
  return (d%1) == 0.0;//Trovo il resto della divisione numero/1 che per definizione è la sua parte decimale e la confronto con il double 0
}

Altro esempio venuto al volo, pero ripeto mi sembra un discorso troppo legato al linguaggio, se ne scegliamo uno vediamo di trovare un algoritmo funzionate ;)
aaa
02/06/14 18:19
amreo
Come ha detto @Roby64 puoi usare l'operatore resto

usa operatore resto
funzione intera(double x)
return x % 1 == 0
end funzione


% è l'operatore modulo e ti da il resto della divisione tra x è 1,
tutti i numeri interi diviso 1 hanno resto 0, invece i numeri con la virgola no

oppure alcuni linguaggi hanno la funzione Int, che permette di togliere la parte decimale
quindi
funzione intera(double x)
return Int(x) = x
end funzione


Per logica se il numero è intero, non viene tolta nessuna parte decimale per cui è uguale e restituisce vero, altrimenti false
Ultima modifica effettuata da amreo 02/06/14 18:22
aaa
03/06/14 6:39
Sì, infatti avevo provato una soluzione simile con la funzione modf() della libreria math.h, ma senza successo.

Sulla scia dei vostri suggerimenti ho ritentato, questa volta in un programmino minimale giusto a scopo di prova.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int Intero( double n ) {
    double intero, decimali;
    decimali = modf( n, &intero );
    return decimali == 0.0;
}


int main() {
    double n = 32.0;

    /* operazioni tanto per far
       qualcosa sul dato */
    n /= 6.0;

    /* aggiungendo queste due,
       la funzione "Intero()"
       diventa inaffidabile */
    n += 12.0;
    n -= 12.0;

    n *= 6.0;

    if( Intero(n) )
        printf( "\n E' un intero\n\n" );
    else printf( "\n Non e' un intero\n\n" );

    return 0;
}


I risultati sono stati scoraggianti!

Cambiando l'ordine delle operazioni a volte Intero() funziona, a volte no.
Controllando col debugger, ho rilevato che con n/=6 immediatamente seguito da n*=6 si ritorna esattamente ad n, ma anche solo con la sequenza...

n /= 6.0;
n += 12.0;
n -= 12.0;
n *= 6.0;


...che in teoria dovrebbe riportare n al punto di partenza, si finisce per avere valori "incontrollabili" alla quindicesima cifra decimale, sufficienti a falsare l'esito della funzione di libreria modf(). In altre parole, n che inizialmente è 32.0 finisce per essere 31.999999999999993. Passando il valore a Intero(), modf() rileva...


intero   == 31
decimali == 0.99999999999999289


Siccome 0.99999999999999289 non è uguale a 0.0, Intero() segnala il valore passato come "non intero".

Insomma, pare ci sia un problema piuttosto grossolano dovuto all'accumulo di arrotondamenti successivi, e non ho idea di come superarlo o "aggirarlo" senza soluzioni un po'... ehm... "discutibili".

======================================

A sentire Code::Blocks pare che il C non ammetta l'uso dell'operatore modulo tra valori a virgola mobile. Ho provato anche quello e non compila, con "error: invalid operands to binary % (have 'double' and 'double')".
Ultima modifica effettuata da 03/06/14 6:45