2009-04-17 18 views
17

Posso confrontare un numero in virgola mobile in un numero intero?Posso confrontare e aggiungere un numero in virgola mobile a un numero intero in C?

Il valore float viene confrontato con numeri interi nel codice?

float f;  // f has a saved predetermined floating-point value to it 
if (f >=100){__asm__reset...etc} 

Inoltre, potrebbe io ...

float f; 
int x = 100; 
x+=f; 

devo usare il valore in virgola mobile f ricevuto da un sistema di riferimento di assetto per regolare un valore di posizione x che controlla un PWM segnale per correggere l'atteggiamento.

risposta

18

Il primo funzionerà correttamente. 100 verrà convertito in float e IEE754 può rappresentare tutti gli interi esattamente come float, fino a circa 2 .

Il secondo funzionerà ma verrà convertito prima in un numero intero, quindi perderai la precisione (è inevitabile se stai trasformando i float in numeri interi).

+0

Grazie, quindi ciò significa che se f = 1.0162 sarebbe int f == 1, quindi dovrei semplicemente ridimensionarlo, f * = 1000; così int f == 1016 per mantenere la precisione? – sevenboarder

+0

Non è possibile rappresentare tutti gli interi esattamente come float. Non con la mantissa a 24 bit di float. Se fosse doppio, sì, ma non float :) – Joey

+0

@Johannes, hai ragione, sto ricordando male una domanda che ho risposto di recente, aggiornato per risolvere il problema. – paxdiablo

0

Sì, funzionerà correttamente. Nello specifico, l'int sarà convertito in float ai fini della conversione. Nella seconda devi lanciare su int ma dovrebbe andare bene altrimenti.

1

LHS definisce la precisione, Così, se il LHS è int e float RHS è, allora questo si traduce in perdita di precisione.

prendere anche uno sguardo a FP relative CFAQ

0

Sì, e qualche volta farò esattamente quello che ci si aspetta.

Come gli altri hanno sottolineato, confrontando, per esempio, 1,0 == 1 funzionerà fuori, perché l'intero 1 è di tipo a getto double (non float) prima del confronto.

Tuttavia, altri confronti non possono.

1

Sì, è possibile confrontarli, è possibile fare matematica su di loro senza troppa attenzione per ciò che è, nella maggior parte dei casi. Ma solo la maggior parte. Il grande bugaboo è che è possibile verificare per f<i ecc., Ma non controllare per f==i. Un intero e un float che "dovrebbero" essere identici nel valore non sono necessariamente identici.

2

È possibile confrontare un float e un intero, certo. Ma il problema che incontrerai è la precisione. Sulla maggior parte delle implementazioni C/C++, float e int hanno la stessa dimensione (4 byte) e livelli di precisione molto diversi. Nessuno dei due tipi può contenere tutti i valori dell'altro tipo. Poiché un tipo non può essere convertito nell'altro tipo senza perdita di precisione e i tipi non possono essere nativi rispetto, fare un confronto senza considerare un altro tipo causerà una perdita di precisione in alcuni scenari.

Quello che puoi fare per evitare perdite di precisione è convertire entrambi i tipi in un tipo che ha una precisione sufficiente a rappresentare tutti i valori di float e int. Sui sistemi più, il doppio farà proprio questo.Così il seguente di solito fa un confronto senza perdita

float f = getSomeFloat(); 
int i = getSomeInt(); 
if ((double)i == (double)f) { 
    ... 
} 
+3

Penso che tu voglia "> =" (per abbinare la domanda originale) e non "==". Test per l'uguaglianza esatta dei numeri in virgola mobile è quasi sempre una cattiva idea. –

10

Dal momento che ti sei identificato come familiarità con le sottigliezze di numeri in virgola mobile, ti rimando a questo bel saggio di David Goldberg: What Every Computer Scientist Should Know About Floating-Point Arithmetic (reprint a Sole).

Dopo aver avuto paura di ciò, la realtà è che più del punto in virgola mobile è un enorme vantaggio per ottenere i calcoli effettuati. E i moderni compilatori e linguaggi (inclusa la C) gestiscono le conversioni in modo sensato in modo da non doverci preoccupare di loro. A meno che tu non lo faccia.

I punti sollevati sulla precisione sono certamente validi. Un IEEE float ha effettivamente solo 24 bit di precisione, che è inferiore a un numero intero a 32 bit. L'utilizzo di double per i calcoli intermedi spinge tutti gli arrotondamenti e le perdite di precisione alla conversione in float o int.

+0

+1 per il collegamento WECSSKAFPA, che mi ha salvato dalla navigazione in corso. :) – unwind

+0

Ho dato una scrematura al foglio, potrei rimandarlo fino a dopo ...haha – sevenboarder

+0

È un po 'pesante in matematica ... ma puoi sfogliare tutte le prove e ottenere i punti importanti. Il punto importante è che non è sempre semplice ... – RBerteig

8

L'aritmetica in modalità mista (aritmetica tra gli operandi di diversi tipi e/o dimensioni) è legale ma fragile. Lo standard C definisce le regole per la promozione del tipo per convertire gli operandi in una rappresentazione comune. La promozione di tipo automatico consente al compilatore di fare qualcosa di sensato per le operazioni in modalità mista, ma "sensibile" non significa necessariamente "corretto".

Per sapere veramente se il comportamento è corretto, è necessario prima comprendere le regole per la promozione e quindi comprendere la rappresentazione dei tipi di dati. In termini molto generali:

  • corta tipi vengono convertiti in tipi più lunghi (float a double, short a int, ecc)
  • tipi interi vengono convertiti in tipi a virgola mobile
  • firmati/unsigned le conversioni favoriscono l'evitamento della perdita di dati (se firmata viene convertita in non firmata o viceversa dipende dalla dimensione dei rispettivi tipi)

Se il codice come x > y (dove x e hanno tipi diversi) è giusto o sbagliato dipende dai valori che possono assumere x e . Nella mia esperienza è prassi comune proibire (tramite lo standard di codifica) conversioni implicite di tipo. Il programmatore deve considerare il contesto ed eseguire esplicitamente qualsiasi tipo di conversione necessaria.

0

A tale proposito, la notazione 1.0 è di tipo double, quindi il confronto è fatto in doppio da regole di promozione tipo come detto prima. 1.f o 1.0f è di tipo float e il confronto sarebbe stato fatto in float. E avrebbe funzionato anche da quando abbiamo detto che 2^23 i primi numeri interi sono rappresentabili in un float.

Problemi correlati