Warum gibt% f große Werte aus, wenn Gleitkommakonstanten anstelle von Variablen übergeben werden?

9

Warum habe ich im angegebenen Programm unterschiedliche Ergebnisse für jedes der printfs erhalten?

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

Und es zeigt die folgende Ausgabe:

44000002048.000000
44000000000.000000
user10056563
quelle
4
Die bisherigen Antworten erklären, dass dies 4.4e10eine doubleKonstante ist, floatin die bei der Initialisierung von konvertiert wird, die cjedoch beibehalten wird, doublewenn sie an übergeben wird printf. Möglicherweise möchten Sie jedoch auch wissen, dass das Hinzufügen eines fSuffixes eine floatKonstante darstellt: Beim Drucken 4.4e10fwird derselbe Wert angezeigt, der sich aus der Initialisierung cauf ergibt 4.4e10f. Die Unterscheidung von floatKonstanten von doubleKonstanten kann wichtig sein, um Qualitätsarbeiten mit Gleitkomma-Arithmetik durchzuführen.
Eric Postpischil
Hat diese Konvertierungsmethode einen Namen? Ich möchte darüber lesen.
user10056563
Möchten Sie wissen, wann die Konvertierung von doublenach floatin der Sprache C erfolgt? Oder möchten Sie wissen, welche Werte sich aus der Konvertierung ergeben, dh welche Auswirkungen die Konvertierung hat? Oder etwas anderes?
Eric Postpischil
Ich stelle weder die Antworten hier noch den Standard in Frage, aber als ich jung war und lernte, haben Cwir printf("%f",x)für a floatund printf("%lf",x)für a verwendet double. Wann haben sich die Dinge geändert? Und wie würde man explizit ein (einzelnes) drucken float- printf("%hf",x)??
Adrian Mole
2
@Adrian %lfin printf ist das gleiche wie %f. Ein floatArgument in einer Variablen wird doublevom Compiler in ein Argument konvertiert , genau wie ein Argument shortin ein int.
SS Anne

Antworten:

9

A floatist ein Typ, der eine 32-Bit-Gleitkommazahl enthält, während die Konstante 4.4e10a darstellt double, die eine 64-Bit-Gleitkommazahl enthält (dh eine Gleitkommazahl mit doppelter Genauigkeit).

Wenn Sie zuweisen 4.4e10, ckann der Wert 4.4e10nicht genau dargestellt werden (ein Rundungsfehler in einem Parameter namens Mantisse), und der nächstmögliche Wert (44000002048) wird gespeichert. Wenn es zu übergeben wird printf, wird sie gefördert zurück zu double, einschließlich der Rundungsfehler.

Im zweiten Fall ist der Wert doubledie ganze Zeit a, ohne sich zu verengen und zu erweitern, und es ist zufällig der Fall, dass a doubleden Wert genau darstellen kann.

Wenn dies ein unerwünschtes Verhalten ist, können Sie dies cals doubleetwas präziser deklarieren (achten Sie jedoch darauf, dass Sie eventuell immer noch an die Genauigkeitsgrenzen stoßen).

Nanofarad
quelle
3

Sie drucken hier tatsächlich die Werte von zwei verschiedenen Typen.

Im ersten Fall weisen Sie einer Variablen vom Typ einen Wert zu float. Die Genauigkeit von a floatbeträgt ungefähr 6 oder 7 Dezimalstellen. Wenn der Wert nicht genau dargestellt werden kann, wird der nächstgelegene Wert angezeigt, der von diesem Typ dargestellt werden kann.

Im zweiten Fall übergeben Sie die Konstante vom 4.4e10Typ double. Dieser Typ hat eine Genauigkeit von ca. 16 Dezimalstellen, und der Wert liegt innerhalb dieses Bereichs, sodass der genaue Wert gedruckt wird.

dbush
quelle
Warum wird am Ende speziell 2048 gedruckt?
user10056563
@ user10056563 Da dies die Nummer 4.4e10 ist, die in einem 32-Bit-Float gespeichert werden kann.
dbush