Znajdź liczbę x z przedziału od 0 do 1 dla którego poniższe wyrażenie zwraca wartość FALSE:
x + 0.1 + 0.1 == 0.1 + 0.1 + x
autor: Przemysław Biecek
Działania w IEEE 754 niekoniecznie są łączne. Tzn: (A + B) + C
może być różne od A + (B + C)
. Tzn: kolejność dodawania może mieć znaczenie. Najwidoczniej dla tych liczb tak właśnie jest.
Chociaż jakoś nie udaje mi się tego zreprodukować w C++.
Edit: dla 0.5 już działa:
0.5 + 0.1 + 0.1 = 0.70000004768371582031250000000000
0.1 + 0.1 + 0.5 = 0.69999998807907104492187500000000
0.1 + 0.4
to dokładnie 0.5
.
Uwielbiam jak ludzie śpią na metodach numerycznych a potem się chwalą takimi odkryciami :D 0.1 to okresowy ułamek binarny.
Znajdź liczbę x z przedziału od 0 do 1 dla którego poniższe wyrażenie zwraca wartość FALSE:
Znaleźć nie problem, wystarczy kilka linii kodu; Gorzej już z wyjaśnieniem dlaczego tak jest :]
uses
{$IFNDEF FPC} Types, {$ENDIF} Math;
var
dblX: Double = 0.0;
begin
while CompareValue(dblX, 1.0) < GreaterThanValue do
begin
WriteLn('x = ', dblX:1:1, ': ', dblX + 0.1 + 0.1 = 0.1 + 0.1 + dblX);
dblX := dblX + 0.1;
end;
ReadLn;
end.
Pod FPC i Delphi7 wyniki takie same, z optymalizacjami i bez:
x = 0.0: TRUE
x = 0.1: TRUE
x = 0.2: TRUE
x = 0.3: TRUE
x = 0.4: TRUE
x = 0.5: FALSE
x = 0.6: FALSE
x = 0.7: FALSE
x = 0.8: FALSE
x = 0.9: TRUE
x = 1.0: TRUE
Co ciekawe, @dam1an podał, że w C# wartość 0.4
da False
- tu jest inaczej.
ta zagadka jest trudna dla mnie ale mam inna :) z matmy :)
y'-x=0
ile wynosi y ? :)
To jest zupełnie nielogiczne, tylko ja odnoszę takie wrażenie? bo:
x + 0.1 + 0.1 = 0.1 + 0.1 + x
x + 0.1 + 0.1 - 0.1 - 0.1 -x = 0
0 = 0 // prawda
Zatem jak kompilator przepuszcza 0.5, 0.6, 0.7, 0.8? :/
To jest zupełnie nielogiczne, tylko ja odnoszę takie wrażenie?
Tak.
Arytmetyka zmiennoprzecinkowa w IEEE 754 nie działa tak jak matematyka, po prostu.
Poczytaj: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
Tam nie ma żadnych zaokrągleń, po prostu ludzie używają niedoskonałego systemu do obliczeń. ;)
if (x == 1.0) cout << "true " else cout << "false ";
powtórzone dwa razy pod rząd wypisuje false true
.
wg mnie znaczenie ma nie tylko zapisanie tych liczb w pamiec ale i dodawanie tych liczb ale i porownanie
na kazdej operacji jest blad
im wiecej operacji liczbowych tym mniejsza dokladnosc
Świetny przykład na pokazanie komuś, dlaczego do biznesowych zastosowań w javie tylko BigDecimal.
Pewnie kiedyś wkleję w gitlabie.
ja za bardzo nie kumam tych systemow cyfrowych ale podobno lepiej sie mnozy niz sumuje chyba sume sie wykonuje iloczynowo jakos
przesuwajac bity w ramce mozemy realizowac mnozenie lub dzielenie przez 2
00000001 - 1
00000010 - 2
00000100 - 4
00001000 - 8
00010000 - 16
Cóż... to zadanie w połączeniu ze stwierdzeniem, że "już wszyscy analitycy klepią w R" utiwerdziło mnie w przekonaniu, że jednak Java ma przed sobą świetlaną przyszłość...
Ten R to w ogóle opłacalny język programowania? Czy taki typowy dla Januszów;) http://www.r-project.org/ Nie ma dobrego kursu, tu chyba pani Lidia z urzędu by się nie połapała.