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.
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 )
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;.
std::numeric_limits<int>::max()
dies größer sein könnte alsstd::numeric_limits<float>::max()
.x
,static_cast<int>(y) != x
(wenn beide sind 32-Bit), aberz
immer noch gleich sein,1.0f
es sei denn ,x == 0
weil beide Zähler und Nenner die gleiche Rundungsfehler haben.x
undy
groß genug sind, und nahe genug zueinander (ohne gleich zu sein), dannx/y
wird wahrscheinlich1.f
auch 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
.Antworten:
Wenn Ihre C ++ - Implementierung IEEE754 verwendet, ist dies garantiert. (Der Divisionsoperator muss den bestmöglichen Gleitkommawert zurückgeben.)
Die einzigen Ausnahmen für
y / y
im allgemeinen nicht zu sein1.f
sind die Fälle , in deneny
istNaN
,+Inf
,-Inf
,0.f
, und-0.f
, oder , wenn Sie auf einer Plattform, woint
so breit ist , dass bestimmte Fälle können es nicht in a dargestellt werden ,float
ohne dassfloat
zu seinem Satz+Inf
oder-Inf
1 . Wenn Sie diesen letzten Punkt beiseite lassen, bedeutet dies in Ihrem Fall, dass diesint 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
int
und einem IEEE754 32 Bitfloat
würde dieses Verhalten für bestimmte Werte von zeigenx
.quelle
y
dass NaN werden kann.NaN
, von denen einige das Vorzeichenbit gesetzt haben. Aber wieNaN != NaN
für jedes Bitmuster von NaN ist es sinnlos zu streiten, ob "+ NaN == -NaN".y
der Wert befand sich sowohl in einem Register als auch im Speicher, und der Compiler hat den Nenner aus dem Speicher geladen. Sie landen also beiy_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?float
nicht enthalten seinx
kann.Nein, nicht in allen Fällen, auch nicht für IEEE754.
Mit erhalten Sie beispielsweise
int x = 0;
NaN. ( Live )quelle
inf
oder0f
oder Varianten von diesen signiert, dann ist das Ergebnis auch nicht1f
float y = x;
mitint x;
.