Rechenprogramm liefert "machmal" falsche Werte
-
Console: Give a: 26 Give b: 27 Ergebnis HS: 369223936.000000 Ergebnis aus Printf: 369223920.000000
War mühseliger, ne neue Compilerversion durch meinen Virenschutz zu schleusen, als das Ding, das übrigens nur pures C ist. Bis aufn Space zuviel Null Problem.
Und es wird anscheinend noch mühseliger, dir Nachdenken beizubringen.
Bei HS liegt der Zieltyp von vorneherein fest, float nämlich. Deswegen wandelt der Compiler vor der Operation auch die Ints in Float um. Bei printf() versucht der Compiler möglichst lange, zeitraubende Float- Umwandlungen/Operationen zu vermeiden, wo genau er zu wandeln beginnt, das weiß ich nicht, aber saiderkan und ich hatten dasselbe Ergebnis und höchstwahrscheinlich unterschiedliche Compiler. Schätzungsweise unterschlagen alle bei 365,25 den Nachkommateil, das wäre ein analytisches Ergebnis. Ausm Standard weiß ich das leider nicht. Kann Dir aber jeder Taschenrechner und ne halbe Gehirnwindung erklären.@Swordfish sagte in Rechenprogramm liefert "machmal" falsche Werte:
Ist auch schon Quatsch. 26 × 27 × 365,25 × 24 × 60 = 369.223.920
Und das Ding ist als double (IEEE754, 64 bit) nicht repräsentierbar. Und als float erst recht nicht.Und jetzt würde ich erstmal sagen, du nüchterst dich erstmal aus ...```cpp
-
@saiderkan float hat nur 6-7 signifikante Stellen.
Das Ergebnis hat aber 9
-
@Swordfish sagte in Rechenprogramm liefert "machmal" falsche Werte:
Ist auch schon Quatsch. 26 × 27 × 365,25 × 24 × 60 = 369.223.920
Und das Ding ist als double (IEEE754, 64 bit) nicht repräsentierbar. Und als float erst recht nicht.Und jetzt würde ich erstmal sagen, du nüchterst dich erstmal aus ...
Du Nachdenken. Dann reden. Bitte Reihenfolge einhalten. Danke. https://abload.de/img/untitled3jksu.png
-
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
Deswegen wandelt der Compiler vor der Operation auch die Ints in Float um.
Nein.
Die Berechnungen sind identisch. a * b als
int
, dann indouble
Bei der Zuweisung an HS geht die Information verloren.printf
kennt keinfloat
. Da wird immerdouble
genommen.
-
@DirkB sagte in Rechenprogramm liefert "machmal" falsche Werte:
@saiderkan float hat nur 6-7 signifikante Stellen.
Das Ergebnis hat aber 9Ja, und? Guck mal, was printf() ggf. macht. Es wandelt einfach um. Wir haben 7 Stellen, der Rest ist Formatgedöns. wieviele Nullen vor oder nach dem Komma angehängt werden, who knows, who cares?
-
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
@DirkB sagte in Rechenprogramm liefert "machmal" falsche Werte:
@saiderkan float hat nur 6-7 signifikante Stellen.
Das Ergebnis hat aber 9Ja, und? Guck mal, was printf() ggf. macht. Es wandelt einfach um. Wir haben 7 Stellen, der Rest ist Formatgedöns. wieviele Nullen vor oder nach dem Komma angehängt werden, who knows, who cares?
double
hat meist 16 Stellen. Und das ist das, was bei der Berechnung beiprintf
genommen wird.
-
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
@DirkB sagte in Rechenprogramm liefert "machmal" falsche Werte:
@saiderkan float hat nur 6-7 signifikante Stellen.
Das Ergebnis hat aber 9Ja, und? Guck mal, was printf() ggf. macht. Es wandelt einfach um. Wir haben 7 Stellen, der Rest ist Formatgedöns. wieviele Nullen vor oder nach dem Komma angehängt werden, who knows, who cares?
Das Ergebnis ist in IEEE754 (also de-facto Standart) als double NAN. Aber ich gebe Dir jetzt einfach Recht. Who cares.@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
Es wandelt einfach um.
Was soll denn da umgewandelt werden? Das zweite Argument von
printf()
(Gegeben daß es syntaktisch richtig wäre) *ist* eindouble
.@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
Schätzungsweise unterschlagen alle bei 365,25 den Nachkommateil, das wäre ein analytisches Ergebnis.
Nein, sicher nicht. Das linke oder rechte Argument von
*
wird promoted. Auswendig weiß ich das jetzt nicht. Ah, da stehts: expr.arith.conv. Der ganze Ausdruk ist danach double.Aber es bringt halt nix weil NAN.
-
@Swordfish also, ganz easy:
int main(int) { int a, b; float hs; printf("Give a: "); scanf("%i", &a); printf("Give b: "); scanf("%i", &b); hs = a * b * 365.25 * 24 * 60; printf("Ergebnis HS: %f\n", hs); printf("Ergebnis aus Printf: %f\n", a * b * 365.25 * 24 * 60); return 0; }
liefert genau den geschilderten Output. Habs für X64 compiliert und die Bitbreite nicht kontrolliert. Aber durchaus aus möglich, daß alles, was nen Zieltyp von float oder mehr hat, mindestens auf double umgebrochen wird., weils dem Prozessor so besser behagt. Guck mal die Eingangswerte an, hehe, das 0.25 von 365,25 wird an irgendeiner Stelle gekappt. Erklärs besser als ich oder liefere dem OP eine bessere Erklärung, zumindest, wie er das pragmatisch zukünftig vermeiden kann. Wäre Forumsgemäß überdies interessant, wie cout das handhabt.
-
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
das 0.25 von 365,25 wird an irgendeiner Stelle gekappt
Nein. Hör bitte endlich auf Deinen Schwachfug zu verbreiten.
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
auf double umgebrochen wird
Nein.
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
wie cout das handhabt.
Wie behandelt!?
Was (zum Teufel) verstehst Du bei "nicht repräsentierbar" nicht?@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
Erklärs besser als ich oder liefere dem OP eine bessere Erklärung, zumindest, wie er das pragmatisch zukünftig vermeiden kann.
Da gibt es keine Lösung à la one kind fits all. Das hängt vom Wertebereich ab.
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
Erklärs besser als ich
Sorry, aber alles was Du bisher tust ist blöd rumraten.
-
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
%f
Warum schreibst Du da
float
hin wenns eindouble
ist?
-
@Swordfish Komisch, du torpedierst einfach mögliche Antworten, ohne sie faktisch widerlegen zu können, hilft dem OP nix.
Ich würde ausnüchtern empfehlen, mir ist das für die fortgeschrittene Stunde zu blöd.
-
@Sarkast Das sind keine Antworten. Und es wäre ... ähm. freundlich von Dir mir nicht ständig Alkoholismus zu unterstellen. Darauf bin ich allergisch. Beantworte lieber die Gegenfragen.
-
Ok. Ich rudere zurück. Gaaaanz fest.
369223920
ist representable. Aber Deine Vorstellung vom Typsystem ist totzdem schräg. Da wird nichts "konvertiert".printf()
kann gar keinefloat
s nehmen.operator<<()
für ostreams erst recht nicht wenn das gefüttertedouble
ist. Und abgeschnitten wird garnichts (bei der Übergabe an betreffende Funktion).Die besseretm Antwort:
Bei der Zeile
// float hs; // ein hoch auf two-letter-identifiers hs = a * b * 365.25 * 24 * 60;
findet implicit ein cast von
double
infloat
statt.Bei
printf("Ergebnis aus Printf: %f\n", a * b * 365.25 * 24 * 60);
bleibt es ein
double
.
-
@Swordfish sagte in Rechenprogramm liefert "machmal" falsche Werte:
Ok. Ich rudere zurück. Haaaanz fest.
369223920
ist representable. Aber Deine Vorstellung vom Typsystem ist totzdem schräg. Da wird nichts "konvertiert".printf()
kann gar keinefloat
s nehmen.operator<<()
für ostreams erst recht nicht. Und abgeschnitten wird garnichts (bei der übergabe an betreffende Funktion).Rudern wir beide zurück.
Also, wir haben den Fakt, daß ich das Ergebnis reproduzieren kann, aber nur sehr, sehr schlicht erklären. So, I'm a simple C- Guy. Halt mal den Kopf schief, ich werd dich nicht ansteigen, aber irgendwas passiert mit den 0,25 und warum und wieso vertage ich für mich auf morgen, was ja schon wieder heute ist. Alles cool?
-
Mit den 0.25 passiert garnichts aufregendes. Alles andere wird zu
double
.Alles easy bro. Aber den Grund für die Ausgabe habe ich oben genannt. Einmal ist es
float
der bei Übergabe anprintf()
in eindouble
gestopft wird und bei der direkten Berechnung als Parameter fürprintf()
eindouble
.Die Nächstmögliche Repräsentation von
369.223.920
alsfloat
(auf üblichen Architekturen, IEEE-sonstwas mit 16 bit) ist 369.223.936
-
@Swordfish ich bin seit 5:00 gestern auf, ich bin alle. Morgen nörgeln wir weiter
-
@Sarkast Siehe edit.
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
ich bin seit 5:00 gestern auf
Sportlich.
-
Das liefert aber gar keine falsche Werte.
-
@Sarkast sagte in Rechenprogramm liefert "machmal" falsche Werte:
@Swordfish ich bin seit 5:00 gestern auf, ich bin alle. Morgen nörgeln wir weiter
Dann lies aber vorher nochmal alle Antworten durch.
-