Dziwny wynik odejmowania dwóch liczb.

0

Proszę o odpowiedź dlaczego otrzymałem taki wynik?

namespace ConsoleApp10
{
class Program
{
static void Main(string[] args)
{
double x = 5.028;
double y = 4.245;

        double s = x - y;

        Console.WriteLine(s);
        
        Console.ReadKey();
    }
}

}

// 0,782999999999999 taki wynik wyświetlił się ???

// a spodziewałem się takiego wyniku odejmowania 0,783 ???

0

Bardzo proszę zobaczyć załącznik.
Nie mogę zrozumieć dlaczego otrzymuje taki wynik:

      5.028 - 4.238   =  0.7899999999999991 !!!!!!! ( a nie 0.790   !!!!!)
1

Czy przeczytałeś materiał, który zalinkował @somekind? Jakie wnioski?

0

Dziękuje za odpowiedź i zainteresowanie moim problemem.
Niestety osobie która stawia pierwsze kroki nie wystarczy podesłać link!!!
Dziękuje Mariuszowi z innej listy dyskusyjnej, który nie tylko wysłał mi link ale w dwóch zdaniach napisał co powinienem zmieć w programie żeby nie mieć takich problemów.

0

Typ Decimal wartości reprezentuje liczbę dziesiętną z przedziału od dodatniej 79,228,162,514,264,337,593,543,950,335 do wartości ujemnej 79,228,162,514,264,337,593,543,950,335. Wartość domyślna Decimal wynosi 0. Typ wartości Decimal jest odpowiedni dla obliczeń finansowych, które wymagają dużej liczby znaczących cyfr całkowitych i ułamkowych, bez błędów zaokrąglania. Typ Decimal nie eliminuje potrzeby zaokrąglania. Zamiast tego minimalizuje błędy ze względu na zaokrąglenie.
C#

https://docs.microsoft.com/pl-pl/dotnet/api/system.decimal.round?view=netframework-4.8

5

To jest smutne. Wydaje Ci sie, że rozwiązałeś problem a tak naprawdę jesteś kolejna osobą, która będzie uważać IEEE754 za programistyczny WTF - i to z lenistwa, bo początkujący nie umie czytać podesłanych materiałów.

0

@mako12 Wejdż sobie tu: http://www.binaryconvert.com/result_double.html?decimal=053046048050056 i tu: http://www.binaryconvert.com/result_double.html?decimal=052046050052053 i zobacz, jak te Twoje liczby są zapisane binarnie.

Mówiąc prosto, w systemie dwójkowym nie można zapisać liczby 5,028 na skończonej liczbie bitów (w Twoim przypadku 64), podobnie jak w systemie dziesiętnym nie można zapisać liczby 1/3 przy użyciu skończonej liczby cyfr. Jeśli miałbyś do dyspozycji tylko 10 cyfr, to zapisałbyś, że 1/3=0,333333333.... Jeśli potem chciałbyś dodać 1/3+1/3+1/3, to dostałbyś 0,999999999.

0

Nie ma sensu czytać kolejnych uszczypliwości, nie na tym polega pomoc.
Jeszcze raz dziękuje wszystkim którzy mi pomogli.

0

Typ decimal Ci nie pomoze chyba ze cos sie zmienilo w najnowszej wersji MidpointRounding.
Ta podlinkowana ma tylko dwa, niepasujace do polskich finansow, tryby zaokraglania.

0
nobody01 napisał(a):

@mako12 Wejdż sobie tu: http://www.binaryconvert.com/result_double.html?decimal=053046048050056 i tu: http://www.binaryconvert.com/result_double.html?decimal=052046050052053 i zobacz, jak te Twoje liczby są zapisane binarnie.

Mówiąc prosto, w systemie dwójkowym nie można zapisać liczby 5,028 na skończonej liczbie bitów (w Twoim przypadku 64), podobnie jak w systemie dziesiętnym nie można zapisać liczby 1/3 przy użyciu skończonej liczby cyfr. Jeśli miałbyś do dyspozycji tylko 10 cyfr, to zapisałbyś, że 1/3=0,333333333.... Jeśli potem chciałbyś dodać 1/3+1/3+1/3, to dostałbyś 0,999999999.

Wielkie dzięki, bardzo mi pomogłeś. Własnie o taką odpowiedź mi chodziło!! Jeszcze raz dziękuje. Odpowiedź konkretna, dająca dużo do myślenia i obrazowo tłumaczy w czym rzecz.

0
vpiotr napisał(a):

Typ decimal Ci nie pomoze chyba ze cos sie zmienilo w najnowszej wersji MidpointRounding.
Ta podlinkowana ma tylko dwa, niepasujace do polskich finansow, tryby zaokraglania.

decimal rozwiązał problem. Drukowałem bardzo dużo odczytów liczników gazowych gdzie w bazie danych były liczby 3,345 , 0,345 ,12,456 itp
i należało odjąć odczyt poprzedni od ostatniego i wydrukować i na szybko. Zmiana double na decimal rozwiązała problem. Zaokrągliłem do 3 miejsc po przecinku wyniki i są czytelne i poprawne. Na szybko o to mi chodziło.

0

Warto też dodać, że Console.WriteLine wykonuje pod spodem pewne zaokrąglenia, przez co czasami inne wartości widzimy w debugerze, a inne w konsoli: https://stackoverflow.com/a/14077656

3

Ten tekst, który podlinkowałem to jest 15-20 minut czytania, no może pół godziny jednym okiem. Mogłeś to zrobić już o 0:52, tymczasem o 8:27 wciąż miałeś ten problem, ale zamiast przeczytać czekałeś na Mariusza z listy dyskusyjnej.
Ja rozumiem, że niektórzy nie szanują czasu innych, ale żeby swojego własnego?

0
somekind napisał(a):

Ten tekst, który podlinkowałem to jest 15-20 minut czytania, no może pół godziny jednym okiem. Mogłeś to zrobić już o 0:52, tymczasem o 8:27 wciąż miałeś ten problem, ale zamiast przeczytać czekałeś na Mariusza z listy dyskusyjnej.
Ja rozumiem, że niektórzy nie szanują czasu innych, ale żeby swojego własnego?

Podesłałeś mi bardzo ciekawy link. Z uwagą go przeczytałem, mam pojęcie na ten temat i większość tam zawartych informacji była mi znana ale nie ukrywam że trochę to już wyleciało mi z pamięci. Bardzo mi pomógł mi też ten link innego Kolegi
http://www.binaryconvert.com/result_double.html?decimal=053046048050056

Nie chciałem Cię urazić i doceniam to, że znalazłeś czas dla mnie i pomogłeś mi w zrozumieniu tematu.
Myślałem, że jeśli mam dokładnie określone dwie liczby i mam je zapisane z taką a nie inna dokładnością to wynik dostane też z tak samą dokładnością.Początkowo myślałem, że popełniam jakiś błąd związany z formatowaniem tekstu. Jakoś mi nie przyszło do głowy, że dwie zmienne dokładnie określone i zapisane dadzą wynik bez zaokrąglenia, aż się prosiło aby tak było skoro założyłem z góry taką dokładność. Gdyby te zmienne nie było odczytane z bazy danych a były wynikiem jakiś obliczeń to bym się tak bardzo nie zdziwił. W tym przypadku sądziłem, że instrukcja wypisywania wyniku "sama pomyśli" i wypisze mi wynik w podobnym formacie. Jeszcze raz dziękuje i przepraszam.

0

Liczby zmiennoprzecinkowe
Po lekturze tego artykułu będziesz wiedział dlaczego 0,1 + 0,2 != 0,3. Dowiesz się w jaki sposób zapisywane są liczby wymierne w pamięci komputera. Poznasz część standardu IEEE754 i zrozumiesz dlaczego część typów nie nadaje się do przechowywania dokładnej reprezentacji liczb wymiernych. Zadania do rozwiązania pomogą Ci utrwalić wiedzę z artykułu.

https://www.samouczekprogramisty.pl/liczby-zmiennoprzecinkowe/

1

Nie tylko sieć się uczy ale też ci którzy szukają odpowiedzi na tam sam problem i mają podane na tacy!! Pozdrawiam.

0

Dziękuję za poruszenie tematu miałem podobny problem

1 użytkowników online, w tym zalogowanych: 0, gości: 1