Loading...
antonfotev avatar antonfotev 4 Точки

При 0.03 % 0.02 ми дава остатък 0.00999999999999997. Защо не е 0.01?

В привидно елементарна задача (няма такива всъщност :) ) реших да подходя със серия от иф-проверки.Кодът е следния:using System;
     using System;
     
public class Program
{
 public static void Main()
 {
 double a = double.Parse(Console.ReadLine());
  double resto = a;
 
        int dvaLieva = 0;
  int edinLev = 0;
  int petdesetSt =0;
  int dvadesetSt = 0;
  int desetDt = 0;
  int petSt = 0;
  int dveSt = 0;
  int ednaSt = 0;
 
  if (resto >= 2)
  {
    dvaLieva = (int)(resto / 2);
    resto = resto % 2;
   Console.WriteLine("dvaLieva: {0}", dvaLieva);
      Console.WriteLine(resto);
  }
  if (resto >= 1)
  {
    edinLev = (int)(resto / 1);
    resto = resto % 1;
   Console.WriteLine("edinLev: {0}", edinLev);
   Console.WriteLine(resto);
  }
  if (resto >= 0.50)
  {
    petdesetSt = (int)(resto / 0.50);
    resto = resto % 0.50;
   Console.WriteLine("petdesetSt: {0}", petdesetSt);
   Console.WriteLine(resto);
  }
  if (resto >= 0.20)
  {
    dvadesetSt = (int)(resto / 0.20);
    resto = resto % 0.20;
   Console.WriteLine("dvadesetSt: {0}", dvadesetSt);
   Console.WriteLine(resto);
  }
  if (resto >= 0.10)
  {
    desetDt = (int)(resto / 0.10);
    resto = resto % 0.10;
   Console.WriteLine("desetDt: {0}", desetDt);
   Console.WriteLine(resto);
  }
  if (resto >= 0.05)
  {
    petSt = (int)(resto / 0.05);
    resto = resto % 0.05;
   Console.WriteLine("petSt: {0}", petSt);
   Console.WriteLine(resto);
  }
  if (resto >= 0.02)
  {
    dveSt = (int)(resto / 0.02);
    resto = resto % 0.02;
   Console.WriteLine("dveSt: {0}", dveSt);
   Console.WriteLine(resto);
  }
  if (resto >= 0.01)
  {
    ednaSt = (int)(resto / 0.01);
    resto = resto % 0.01;
   Console.WriteLine("ednaSt: {0}", ednaSt);
   Console.WriteLine(resto);
  }
 
  int numberMoneyResto = dvaLieva + edinLev + petdesetSt + dvadesetSt + desetDt + petSt + dveSt + ednaSt;
  Console.WriteLine("Number money resto is {0}: " , numberMoneyResto);
 
 }
}

при въведена стойност 1.23
би трябвало да даде резултат четири: монета от 1лв, монета от 20ст, монета от 2ст и монета от 1ст.
обаче
това е, което всъщност се получава:
1.23
edinLev: 1
0.23
dvadesetSt: 1
0.03
dveSt: 1
0.00999999999999997
Number money resto is 3:
когато 0.03 % 0.02 би трябвало остатъкът да е 0.01.
Тогава ще влезе в последния иф
Но вместо това  0.03 % 0.02 ми дава 0.00999999999999997


Опитах и по друг начин:

using System;
                    
public class Program
{
    public static void Main()
    {
    double a = double.Parse(Console.ReadLine());
        int currentNumber = 0;
        double numberresto = 0;
        
        if (a >= 2)
        {
         currentNumber = (int)(a /2);
         numberresto = numberresto +  currentNumber;
         a = a - 2 * currentNumber;    
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);
        }
        if (a >= 1)
        {
         currentNumber = (int)(a /1);
         numberresto = numberresto +  currentNumber;
         a = a - currentNumber;
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);
        }
        if (a >= 0.50)
        {
         currentNumber = (int)(a / 0.50 );
         numberresto = numberresto +  currentNumber;
         a = a - 0.50 * currentNumber;
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);            
        }
        if (a >= 0.20)
        {
         currentNumber = (int)(a / 0.20 );
         numberresto = numberresto +  currentNumber;
         a = a - 0.20 * currentNumber;
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);            
        }
        if (a >= 0.10)
        {
         currentNumber = (int)(a / 0.10 );
         numberresto = numberresto +  currentNumber;
         a = a - 0.10 * currentNumber;
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);            
        }
        if (a >= 0.05)
        {
         currentNumber = (int)(a / 0.05 );
         numberresto = numberresto +  currentNumber;
         a = a - 0.05 * currentNumber;    
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);            
        }
        if (a >= 0.02)
        {
         currentNumber = (int)(a / 0.02 );
         numberresto = numberresto +  currentNumber;
         a = a - 0.02 * currentNumber;    
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);            
        }
        if (a >= 0.01)
        {
         currentNumber = (int)(a / 0.01 );
         numberresto = numberresto +  currentNumber;
         a = a - 0.01 * currentNumber;    
            Console.WriteLine(currentNumber);
            Console.WriteLine(a);            
        }
        Console.WriteLine(numberresto);
    }
}

После въведох същата входна стойност и отново получих 0.00999999999999997 вместо 0.01

1.23
1
0.23
1
0.03
1
0.00999999999999997
3

Тагове:
0
Programming Basics
NikolaMilushev avatar NikolaMilushev 1 Точки

Здравей, Антон, можеш да прочетеш следната статия, по-точно секцията Rounding Error.

https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

В твоя случай можеш да замениш типа double с тип decimal. Последният е препоръчван за изчисления свързани с пари, тъй като е с по-голяма прецизсност спрямо double и float. 

0
luskos avatar luskos 5 Точки

На кратко при работа с фракции има загуби.

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.