2011-12-18 7 views
8

Ecco il problema: i totali di gioco possono essere giocati da un numero qualsiasi di persone. Inizia con un totale di 100 e ogni giocatore a turno effettua uno spostamento intero tra -20 e 20 a quel totale. Il vincitore è il giocatore la cui regolazione rende il pari complessivamente a 5. Utilizzando solo i tre variabili data: totale regolazione contatore Ecco quello che ho finora:Determinare se un float ha una parte frazionaria?

#include <stdio.h> 
int main (void) 
{ 
    int counter=0; 
    float adj; 
    int ttl=100; 

    printf("You all know the rules now lets begin!!!\n\n\nWe start with 100. What is\n"); 

    while (ttl!=5) 
    { 
     printf("YOUR ADJUSTMENT?"); 
     scanf("%f",&adj); 
     counter++; 
     if (adj<=20 && adj>=-20) 
     { 
     ttl=ttl+adj; 
     printf("The total is %d\n",ttl); 
     } 
     else 
     { 
     printf ("I'm sorry. Do you not know the rules?\n"); 
     } 
    } 
    printf("The game is won in %d steps!",counter); 

} 

Che cosa ho bisogno: Quando un il numero decimale è inserito va al resto. Come posso determinare se un float ha una parte frazionaria.

+0

A livello binario, nessun numero in virgola mobile ha un decimale. http://en.wikipedia.org/wiki/IEEE_754-2008 –

+0

Stiamo parlando di galleggianti qui. Ha sempre "un decimale". Usa invece un 'double'. (FYI @Chris e intendo lo stesso) –

+2

@TomvanderWoerdt: Che differenza fa 'double'? –

risposta

3

se si desidera sapere se un numero reale x non ha alcuna parte frazionaria, provare x==floor(x).

+0

@sarnold, non in questo caso, no. Gli interi che possono essere rappresentati come 'float' o' double' sono rappresentati esattamente e 'floor' non fa errori con quelli che non lo sono. – lhf

+0

Grazie per la risposta più dettagliata. :) – sarnold

+0

Non sono convinto che tutte le risposte che utilizzano questa tecnica siano solide. Se 'adj' è in realtà il risultato di un calcolo intermedio, può essere contenuto in un registro di precisione estesa. Quindi il confronto può restituire 'false', anche se in seguito' adj' viene controllato, in realtà risulta essere un valore intero. –

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

int main() 
{ 
    float param, fractpart, intpart; 

    param = 3.14159265; 
    fractpart = modff (param , &intpart); 
    return 0; 
} 

http://www.cplusplus.com/reference/clibrary/cmath/modf/

modff trova la parte frazionaria, quindi credo che il test se è uguale o 0null sarà rispondere alla tua domanda.

+0

dovresti essere la risposta accettata, grazie! – VivienLeger

13

È possibile trasmettere lo float a int e quindi confrontarlo con la variabile originale. Se sono uguali non c'è stata una parte frazionale.

Utilizzando questo metodo non è necessaria una variabile temporanea o una chiamata di funzione.

float adj; 

    ....  

    if (adj == (int)adj) 
    printf ("no fractional!\n"); 
    else 
    printf ("fractional!\n"); 

Spiegazione

Dal momento che un int non può gestire le frazioni il valore della vostra float verrà troncato in un int (ad esempio (float)14.3 verrà troncato in (int)14).

Quando si confrontano 14 in 14.3 è ovvio che non hanno lo stesso valore e quindi "frazionale!" sarà stampato

+2

Non hai bisogno del cast esplicito per 'float', verrà cast automaticamente. La tua soluzione non è sbagliata, l'avrei appena scritta come 'f == (int) f', che trovo più facile da leggere e capire. – Kevin

+0

@Kevin Ho modificato che allo stesso tempo hai scritto il tuo commento, ho poi aggiunto qualche altra informazione riguardo l'argomento, grazie. –

+2

Non sono convinto che tutte le risposte che usano questa tecnica siano solide.Se 'adj' è in realtà il risultato di un calcolo intermedio, può essere contenuto in un registro di precisione estesa. Quindi il confronto può restituire 'false', anche se in seguito' adj' viene controllato, in realtà risulta essere un valore intero. –

0

L'utilizzo di scanf() è problematico. Se l'utente digitava -5 +10 -15 -15 sulla prima riga di input, quindi premi Invio, elaboreresti i 4 numeri a turno con scanf(). Questo probabilmente non è quello che volevi. Inoltre, naturalmente, se l'utente digita +3 or more, la prima conversione si interrompe una volta letto lo spazio e tutte le successive conversioni non riescono sullo o o or e il codice entra in un ciclo. È necessario verificare il valore di ritorno da scanf() per sapere se è stato in grado di convertire qualsiasi cosa.

I problemi read-ahead sono sufficientemente grave che mi piacerebbe andare per il quasi-standard alternativo di utilizzare fgets() per leggere una riga di dati, e quindi utilizzando sscanf() (che in più s è tutto importante) per analizzare un numero.

Per determinare se un numero in virgola mobile ha una parte frazionaria, nonché una parte intera, è possibile utilizzare la funzione di modf() or modff() - quest'ultimo dal vostro adj è un float:

#include <math.h> 

double modf(double x, double *iptr); 
float modff(float value, float *iptr); 

Il valore di ritorno è il parte frazionaria firmata di x; il valore in iptr è la parte intera. Si noti che modff() potrebbe non essere disponibile nei compilatori (librerie di runtime) che non supportano C99. In tal caso, potrebbe essere necessario utilizzare double e modf(). Tuttavia, è probabilmente altrettanto semplice limitare l'utente a inserire numeri interi con il formato %d e un tipo intero per adj; questo è quello che avrei fatto sin dall'inizio.

Un altro punto di dettaglio: vuoi davvero contare i numeri non validi nel numero totale di tentativi?

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

int main(void) 
{ 
    int counter=0; 
    int ttl=100; 

    printf("You all know the rules now lets begin!!!\n" 
      "\n\nWe start with 100. What is\n"); 

    while (ttl != 5) 
    { 
     char buffer[4096]; 
     float a_int; 
     float adj; 

     printf("YOUR ADJUSTMENT?"); 
     if (fgets(buffer, sizeof(buffer), stdin) == 0) 
      break; 
     if (sscanf("%f", &adj) != 1) 
      break; 
     if (adj<=20 && adj>=-20 && modff(adj, &a_int) == 0.0) 
     { 
      counter++; // Not counting invalid numbers 
      ttl += adj; 
      printf("The total is %d\n", ttl); 
     } 
     else 
     { 
      printf ("I'm sorry. Do you not know the rules?\n"); 
     } 
    } 

    if (ttl == 5) 
     printf("The game is won in %d steps!\n", counter); 
    else 
     printf("No-one wins; the total is not 5\n"); 
    return(0); 
} 

Chiaramente, io sto diligentemente ignorando la possibilità che qualcuno potrebbe digitare in più di 4095 caratteri prima di digitare ritorno.

0

Sto solo imparando C quindi dimmi se ho torto, per favore.

Ma se invece di usare

scanf("%f",&adj); 

se utilizzare:

scanf("%d%d", &adj, &IsUndef); 

Quindi, se l'utente ha digitato qualcosa di diverso da un numero intero & IsUndef non sarebbe uguale NULL e deve avere una parte frazionaria inviando l'utente a altro.

forse.