Ist eine durch sich selbst geteilte ganze Zahl Float garantiert 1.f?

76

Wenn ich schreibe:

int x = /* any non-zero integer value */;
float y = x;
float z = y / y;

Ist zgarantiert genau 1.f?

jb
quelle
8
Es würde eine ziemlich ungewöhnliche Menge an Pedanterie erfordern, selbst für C ++ - Standards, um zu argumentieren, dass std::numeric_limits<int>::max()dies größer sein könnte als std::numeric_limits<float>::max().
MSalters
2
@ MSalters Haha, ich habe darüber nachgedacht, aber entschieden, dass es zu dumm ist. :)
Baum mit Augen
1
@MSalters: FWIW, für die meisten x, static_cast<int>(y) != x(wenn beide sind 32-Bit), aber zimmer noch gleich sein, 1.0fes sei denn , x == 0weil beide Zähler und Nenner die gleiche Rundungsfehler haben.
Arne Vogel
Wenn zwei Zahlen xund ygroß genug sind, und nahe genug zueinander (ohne gleich zu sein), dann x/ywird wahrscheinlich 1.fauch aufgrund eines Fehlers bei der Umwandlung. Geben Sie dies in die Konsole Ihres Browsers ein (die wahrscheinlich auch IEEE754 verwendet) und drücken Sie die EINGABETASTE : 9223372036854775700/9223372036854775800.
Cássio Renan
1
@ArneVogel: Eigentlich ist + INF / + INF NaN, nicht 1.0
MSalters

Antworten:

96

Wenn Ihre C ++ - Implementierung IEEE754 verwendet, ist dies garantiert. (Der Divisionsoperator muss den bestmöglichen Gleitkommawert zurückgeben.)

Die einzigen Ausnahmen für y / yim allgemeinen nicht zu sein 1.fsind die Fälle , in denen yist NaN, +Inf, -Inf, 0.f, und -0.f, oder , wenn Sie auf einer Plattform, wo intso breit ist , dass bestimmte Fälle können es nicht in a dargestellt werden , floatohne dass floatzu seinem Satz +Infoder -Inf1 . Wenn Sie diesen letzten Punkt beiseite lassen, bedeutet dies in Ihrem Fall, dass dies int x = 0;die einzige Ausnahme darstellt.

IEEE754 ist extrem verbreitet. Aber um sicherzugehen, testen Sie den Wert von

std::numeric_limits<float>::is_iec559;

1 Eine Plattform mit beispielsweise 128 Bit intund einem IEEE754 32 Bit floatwürde dieses Verhalten für bestimmte Werte von zeigen x.

Bathseba
quelle
2
Ich glaube nicht, ydass NaN werden kann.
Baum mit Augen
2
Wenn Sie diesen Weg gehen möchten, müssen Sie auch Inf, -Inf und -0f hinzufügen. :)
Baum mit Augen
2
@BaummitAugen: Es gibt viele IEE754-Bitmuster NaN, von denen einige das Vorzeichenbit gesetzt haben. Aber wie NaN != NaNfür jedes Bitmuster von NaN ist es sinnlos zu streiten, ob "+ NaN == -NaN".
MSalters
1
Angenommen, yder Wert befand sich sowohl in einem Register als auch im Speicher, und der Compiler hat den Nenner aus dem Speicher geladen. Sie landen also bei y_from_register / y_from_memory. Wenn das Register eine höhere Genauigkeit als der Speicher hat, was ist die Garantie dafür, dass 1 das beste Teilungsergebnis ist?
David Schwartz
1
Eine weitere Ausnahme ist, wenn der Wert floatnicht enthalten sein xkann.
Nat
33

Nein, nicht in allen Fällen, auch nicht für IEEE754.

Mit erhalten Sie beispielsweise int x = 0;NaN. ( Live )

Baum mit Augen
quelle
Hab das einfach in meine Antwort aufgenommen, bevor du das gepostet hast. Habe eine Gegenstimme.
Bathsheba
Ich fand Ihre Formulierung mehrdeutig und irreführend, daher habe ich eine Änderung vorgeschlagen, um sie klarer zu machen.
Katze
3
@cat Ich kann den Teil "nicht in allen Fällen" Ihres Vorschlags verstehen, aber Ihre Verwendung von "Zum Beispiel" legt nahe, dass es andere Werte gibt, für die das Gleiche gilt, und aus diesem Grund denke ich persönlich, dass die Antwort hier ist Jetzt ist besser als die Antwort, die Sie vorgeschlagen haben.
@hvd wenn y ist infoder 0foder Varianten von diesen signiert, dann ist das Ergebnis auch nicht1f
Katze
3
@cat Die Frage bezieht sich speziell auf eine ganze Zahl float geteilt durch sich selbst und hat float y = x;mit int x;.