Gibt es eine Möglichkeit, programmgesteuert das Double zu erhalten, das 1.0 am nächsten kommt, aber nicht 1.0 ist?
Ein hackiger Weg, dies zu tun, wäre, das Double auf eine gleich große Ganzzahl zu speichern und dann eine zu subtrahieren. So wie IEEE754-Gleitkommaformate funktionieren, würde dies dazu führen, dass der Exponent um eins verringert wird, während der Bruchteil von allen Nullen (1.000000000000) auf alle Einsen (1.111111111111) geändert wird. Es gibt jedoch Maschinen, auf denen Ganzzahlen als Little-Endian und Gleitkomma als Big-Endian gespeichert sind, sodass dies nicht immer funktioniert.
c++
floating-point
floating-accuracy
jorgbrown
quelle
quelle
nextafter()
ist der einzig richtige Weg, um das zu erreichen, was er will.1.0000...
Binär eine Dekrementierung ist0.111111....
und um sie zu normalisieren, müssen Sie sie nach links verschieben.1.11111...
Dazu müssen Sie den Exponenten dekrementieren. Und dann sind Sie 2 ulp von 1.0 entfernt. Nein, wenn Sie einen vom Integralwert abziehen, erhalten Sie NICHT das, was hier gefragt wird.Antworten:
In C und C ++ ergibt Folgendes den Wert, der 1.0 am nächsten kommt:
Beachten Sie jedoch, dass in späteren Versionen von C ++
limits.h
zugunsten von veraltet istclimits
. Wenn Sie jedoch ohnehin C ++ - spezifischen Code verwenden, können Sie diesen verwendenUnd wie Jarod42 in seiner Antwort schreibt, können Sie seit C99 oder C ++ 11 auch Folgendes verwenden
nextafter
:Natürlich können (und sollten für spätere C ++ - Versionen) in C ++ stattdessen eingeschlossen
cmath
und verwendetstd::nextafter
werden.quelle
Seit C ++ 11 können Sie verwenden
nextafter
, um den nächsten darstellbaren Wert in die angegebene Richtung zu erhalten:Demo
quelle
std::ceil(std::nextafter(1., std::numeric_limits<double>::max()))
.nextafter
, und so implementiert musl es, falls jemand anderes sehen möchte, wie es gemacht wird. Grundsätzlich: rohes bisschen Twiddling.In C können Sie Folgendes verwenden:
DBL_EPSILON
ist die Differenz zwischen 1 und dem kleinsten Wert größer als 1, der darstellbar ist.Sie müssen es auf mehrere Ziffern drucken, um den tatsächlichen Wert zu sehen.
Auf meiner Plattform
printf("%.16lf",1.0+DBL_EPSILON)
gibt1.0000000000000002
.quelle
1.
als1'000'000
Demo1.0
. Übrigens gibt es auch den nächsten Wert größer als 1 und nicht den absolut nächsten Wert 1 (der möglicherweise kleiner als 1 ist). Ich stimme zu, dass dies eine teilweise Antwort ist, aber ich dachte, dass sie dennoch dazu beitragen könnte.In C ++ können Sie dies auch verwenden
quelle