Wie sind diese Werte mit doppelter Genauigkeit auf 20 Dezimalstellen genau?

Ich teste einige sehr einfache Äquivalenzfehler, wenn Genauigkeit ein Problem ist, und wollte die Operationen mit erweiterter doppelter Genauigkeit ausführen (sodass ich wusste, wie die Antwort aus ~ 19 Ziffern bestehen würde) und dann dieselben Operationen mit doppelter Genauigkeit ausführen ( wo es einen Rundungsfehler in der 16. Stelle geben würde), aber irgendwie behält meine Arithmetik mit doppelter Genauigkeit 19 Stellen Genauigkeit bei.

Wenn ich die Operationen in Extended Double durchführe und dann die Zahlen in einer anderen Fortran-Routine fest codiere, erhalte ich die erwarteten Fehler, aber ist hier etwas Merkwürdiges los, wenn ich einer Variable mit doppelter Genauigkeit eine Variable mit doppelter Genauigkeit zuordnet?

program code_gen
    implicit none 
    integer, parameter :: Edp = selected_real_kind(17)
    integer, parameter :: dp = selected_real_kind(8)
    real(kind=Edp) :: alpha10, x10, y10, z10 
    real(kind=dp) :: alpha8, x8, y8, z8

    real(kind = dp) :: pi_dp = 3.1415926535897932384626433832795028841971693993751058209749445

    integer :: iter
    integer :: niters = 10

    print*, 'tiny(x10) = ', tiny(x10)
    print*, 'tiny(x8)  = ', tiny(x8)
    print*, 'epsilon(x10) = ', epsilon(x10)
    print*, 'epsilon(x8)  = ', epsilon(x8)

    do iter = 1,niters
        x10 = rand()
        y10 = rand()
        z10 = rand()
        alpha10 = x10*(y10+z10)

        x8 = x10 
        x8 = x8 - pi_dp
        x8 = x8 + pi_dp
        y8 = y10 
        y8 = y8 - pi_dp
        y8 = y8 + pi_dp
        z8 = z10 
        z8 = z8 - pi_dp
        z8 = z8 + pi_dp
        alpha8 = alpha10

        write(*, '(a, es30.20)') 'alpha8 .... ', x8*(y8+z8)
        write(*, '(a, es30.20)') 'alpha10 ... ', alpha10

        if( alpha8 .gt. x8*(y8+z8) ) then
            write(*, '(a)') 'ERROR(.gt.)'
        elseif( alpha8 .lt. x8*(y8+z8) ) then
            write(*, '(a)') 'ERROR(.lt.)'
        endif
    enddo
end program code_gen

worand() ist die Gfortran-Funktion gefundenHie.

Wenn es sich nur um einen Präzisionstyp handelt (z. B. double), können wir machine epsilon als @ bezeichneE16 was ungefähr @ i2.22E-16. Wenn wir einfach zwei reelle Zahlen addieren,x+y, dann ist die resultierende Maschine ausgedrückt Zahl(x+y)*(1+d1) woabs(d1) < E16. Ebenso, wenn wir dann diese Zahl mit @ multiplizierz, der resultierende Wert ist wirklich(z*((x+y)*(1+d1))*(1+d2)) das ist fast(z*(x+y)*(1+d1+d2)) woabs(d1+d2) < 2*E16. Wenn wir jetzt zu erweiterter doppelter Präzision übergehen, dann ist das einzige, was sich ändert, dassE16 wendet sich anE20 und hat einen Wert von ungefähr1.08E-19.

Meine Hoffnung war, die Analyse in erweiterter doppelter Genauigkeit durchzuführen, damit ich zwei Zahlen vergleichen konnte, diesollt ist gleich, zeigt aber, dass gelegentlich Rundungsfehler dazu führen, dass Vergleiche fehlschlagen. Durch die Zuweisung vonx8=x10, Ich hatte gehofft, eine 'Version' mit doppelter Genauigkeit des erweiterten Werts mit doppelter Genauigkeit zu erstellenx10, wobei nur die ersten ~ 16 Stellen vonx8 entspricht den Werten vonx10, aber beim Ausdrucken der Werte wird angezeigt, dass alle 20 Stellen gleich sind und der erwartete Rundungsfehler mit doppelter Genauigkeit nicht wie erwartet auftritt.

Es sollte auch beachtet werden, dass ich vor diesem Versuch ein Programm geschrieben habe, das tatsächlich @ schreibEin weitere Programm, in dem die Werte vonx, y, undz sind auf 20 Dezimalstellen 'hartcodiert'. In dieser Programmversion werden die Vergleiche von.gt. und.lt. ist wie erwartet fehlgeschlagen, aber ich kann dieselben Fehler nicht duplizieren, indem ich einen erweiterten Wert mit doppelter Genauigkeit als Variable mit doppelter Genauigkeit umsetze.

ei dem Versuch, die Werte mit doppelter Genauigkeit weiter zu stören und einen Rundungsfehler hinzuzufügen, habe ich hinzugefügt und dann subtrahierpi von meinen Variablen mit doppelter Genauigkeit, die die verbleibenden Variablen mit einem Rundungsfehler mit doppelter Genauigkeit belassen sollten, aber ich sehe das immer noch nicht im Endergebnis.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage