Perché% f stampa valori elevati quando vengono passate costanti in virgola mobile anziché variabili?


9

Nel programma dato perché ho ottenuto risultati diversi per ciascuna delle printfs?

#include <stdio.h>
int main()
{
    float c = 4.4e10;
    printf("%f\n", c);
    printf("%f\n", 4.4e10);
    return 0;
}

E mostra il seguente output:

44000002048.000000
44000000000.000000

4
Le risposte finora spiegano che 4.4e10è una doublecostante che viene convertita floatnell'inizializzazione cma mantenuta come una doublevolta passata a printf. Tuttavia, potresti anche sapere che l'aggiunta di un fsuffisso lo rende una floatcostante: la stampa 4.4e10fmostrerà lo stesso valore che risulta dall'inizializzazione ca 4.4e10f. Distinguere le floatcostanti dalle doublecostanti può essere importante per svolgere un lavoro di qualità con l'aritmetica in virgola mobile.
Eric Postpischil,

Questo metodo di conversione ha un nome? Voglio leggerlo.
user10056563

Vuoi sapere quando la conversione da doublea floatverifica nel linguaggio C? Oppure vuoi sapere quali valori derivano dalla conversione, ovvero quali effetti ha la conversione? O qualcos'altro?
Eric Postpischil,

Non sto mettendo in discussione le risposte qui lo standard, ma, quando ero giovane e imparando, Cabbiamo usato printf("%f",x)per un floate printf("%lf",x)per un double. Quando sono cambiate le cose? E come si potrebbe esplicitamente stampare un (singolo) float- printf("%hf",x)??
Adrian Mole,

2
@Adrian %lfin printf è la stessa cosa di %f. A floatin un argomento variabile viene convertito in a doubledal compilatore, proprio come un shortviene convertito in un int.
SS Anne

Risposte:


9

A floatè un tipo che contiene un numero in virgola mobile a 32 bit, mentre la costante 4.4e10rappresenta un double, che contiene un numero in virgola mobile a 64 bit (ovvero un numero in virgola mobile a doppia precisione)

Quando si assegna 4.4e10a c, il valore 4.4e10non può essere rappresentato con precisione (un errore di arrotondamento in un parametro chiamato mantissa) e viene memorizzato il valore più vicino possibile (44000002048). Quando viene passato printf, viene promosso nuovamente double, incluso l'errore di arrotondamento.

Nel secondo caso, il valore è doubletutto il tempo, senza restringimento e allargamento, e capita che a doublepossa rappresentare esattamente il valore.

Se questo è un comportamento indesiderato, puoi dichiararlo ccome doubleper un po 'più di precisione (ma attenzione che alla fine continuerai a raggiungere i limiti di precisione).


3

In realtà stai stampando i valori di due diversi tipi qui.

Nel primo caso stai assegnando un valore a una variabile di tipo float. La precisione di a floatè di circa 6 o 7 cifre decimali, quindi a meno che il valore non possa essere rappresentato esattamente vedrai il valore più vicino che può essere rappresentato da quel tipo.

Nel secondo caso stai passando la costante 4.4e10che ha tipo double. Questo tipo ha circa 16 cifre decimali di precisione e il valore è compreso in quell'intervallo, quindi viene stampato il valore esatto.


Perché stampa specificamente il 2048 alla fine?
user10056563

@ user10056563 Perché questo è il numero più vicino a 4.4e10 che può essere memorizzato in un float a 32 bit.
dbush,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.