Много странен казус
Дълго е да описвам как стигнах до този резултат, но е в опитите ми да реша проста задача от курса Programing Baiscs. Проблема е че при елементарно умножение Visual Studio вади не верни резултати:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
double quantity = double.Parse(Console.ReadLine());
Console.WriteLine(quantity * 6);
}
}
}
При въвеждане на 1.2 би трябвало да вади 7.2 но вади абсурден резултат от 7.1989999 и т.н. някаква идея защо?
Да прочетох, но малко не ми стана ясно.... ако става дума за някаква сериозна прецизност бих разбрал но за 6 * 1.2 e абсурдно, пък и judge поради това ми връща грешка, а за decimal още не сме учили и съм малко параграф 22. Кода като логика би трябвало да работи но ми връща грешки заради точността на вида променлива?!
Пусни ми някакво условие на задачата и ще ти я разясня....сори че те занимвам с работи които не сте взели още :)
Грешки при пресмятания с реални типове При пресмятания с реални типове данни с плаваща запетая е възможно да наблюдаваме странно поведение, тъй като при представянето на дадено реално число много често се губи точност. Причината за това е невъзмож ността някои реални числа да се представят точно сума от отрицателни степени на числото 2. Примери за числа, които нямат точно представяне в типовете float и double, са например 0.1, 1/3, 2/7 и други. Следва примерен C# код, който демонстрира грешките при пресмятания с числа с плаваща запетая в C#: float f = 0.1f; Console.WriteLine(f); // 0.1 (correct due to rounding) double d = 0.1f; Console.WriteLine(d); // 0.100000001490116 (incorrect) float ff = 1.0f / 3; Console.WriteLine(ff); // 0.3333333 (correct due to rounding) double dd = ff; Console.WriteLine(dd); // 0.333333343267441 (incorrect) Причината за неочаквания резултат в първия пример е фактът, че числото 0.1 (т.е. 1/10) няма точно представяне във формата за реални числа с плаваща запетая IEEE 754 и се записва в него с приближение. При непо средствено отпечатване резултатът изглежда коректен заради закръглява нето, което се извършва скрито при преобразуването на числото към стринг. При преминаване от float към double грешката, получена заради приближеното представяне на числото в IEEE 754 формат става вече явна и не може да бъде компенсирана от скритото закръгляване при отпечатва нето и съответно след осмата значеща цифра се появяват грешки. Глава 2. Примитивни типове и променливи 123 При втория случай числото 1/3 няма точно представяне и се закръглява до число, много близко до 0.3333333. Кое е това число се вижда отчетливо, когато то се запише в типа double, който запазва много повече значещи цифри. И двата примера показват, че аритметиката с числа с плаваща запетая може да прави грешки и по тази причина не е подходяща за прецизни финансови пресмятания. За щастие C# поддържа аритметика с десетична точност, при която числа като 0.1 се представят в паметта без закръгляне. Не всички реални числа имат точно представяне в типо вете float и double. Например числото 0.1 се представя закръглено в типа float като 0.099999994. Реални типове с десетична точност В C# се поддържа т. нар. десетична аритметика с плаваща запетая (decimal floating-point arithmetic), при която числата се представят в десетична, а не в двоична бройна система и така не се губи точност при записване на десетично число в съответния тип с плаваща запетая. Типът данни за реални числа с десетична точност в C# е 128-битовият тип decimal. Той има точност от 28 до 29 десетични знака. Минималната му стойност е -7.9×1028, а максималната е +7.9×1028. Стойността му по подразбиране е 0.0м или 0.0М. Символът 'm' накрая указва изрично, че числото е от тип decimal (защото по подразбиране всички реални числа са от тип double). Най-близките до 0 числа, които могат да бъдат записани в decimal са ±1.0 × 10-28. Видно е, че decimal не може да съхранява много големи положителни и отрицателни числа (например със стотици цифри), нито стойности много близки до 0. За сметка на това този тип почти не прави грешки при финансови пресмятания, защото представя числата като сума от степени на числото 10, при което загубите от закръгляния са много по-малки, отколкото когато се използва двоично представяне. Реалните числа от тип decimal са изключително удобни за пресмятания с пари – изчисляване на приходи, задължения, данъци, лихви и т.н. Следва пример, в който декларираме променлива от тип decimal и й присвояваме стойност: decimaldecimalPI=3.14159265358979323846m;Console.WriteLine(decimalPI); // 3.14159265358979323846 Числото decimalPI, което декларирахме от тип decimal, не е закръглено дори и с един знак, тъй като го зададохме с точност 21 знака, което се побира в типа decimal без закръгляне. 124 Въведение в програмирането със C# Много голямата точност и липсата на аномалии при пресмятанията (каквито има при float и double) прави типа decimal много подходящ за финансови изчисления, където точността е критична. Въпреки по-малкия си обхват, типът decimal запазва точ ност за всички десетични числа, които може да побере! Това го прави много подходящ за прецизни сметки, най често финансови изчисления. Основната разлика между реалните числа с плаваща запетая реалните числа с десетична точност е в точността на пресмятанията и в степента, до която те закръглят съхраняваните стойности. Типът double позволява работа с много големи стойности и стойности много близки до нулата, но за сметка на точността и неприятни грешки от закръгляне. Типът decimal има по-малък обхват, но гарантира голяма точност при пресмятанията и липсва на аномалии с десетичните числа. decimal, а не float или double. В противен случай може да се натъкнете на неприятни аномалии при пресмятанията и Ако извършвате пресмятания с пари използвайте типа грешки в изчисленията! Тъй като всички изчисления с данни от тип decimal се извършват чисто софтуерно, а не директно на ниско ниво в микропроцесора, изчисленията с този тип са от няколко десетки до стотици пъти по-бавни, отколкото същите изчисления с double, така че ползвайте този тип внимателно.
Това е кода който ми прави проблем при въвъждане от конзолата на
water
Plovdiv
3
би трябвало да излезе 2.1, а VS вади 2.0999999999999996 и се опитах да парсна decimal ама ми дава грешка в синтаксиса :(
using System;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
string product = Console.ReadLine();
string city = Console.ReadLine();
double amount = double.Parse(Console.ReadLine());
double price = 0;
// Main variable definition
if (city == "Sofia")
{
switch (product)
{
case "coffee":
price = 0.50;
break;
case "water":
price = 0.80;
break;
case "beer":
price = 1.20;
break;
case "sweets":
price = 1.45;
break;
case "peanuts":
price = 1.60;
break;
default:
Console.WriteLine("error");
break;
}
double total = price * amount;
Console.WriteLine(total);
}
else if (city == "Plovdiv")
{
switch (product)
{
case "coffee":
price = 0.40;
break;
case "water":
price = 0.70;
break;
case "beer":
price = 1.15;
break;
case "sweets":
price = 1.30;
break;
case "peanuts":
price = 1.50;
break;
default:
Console.WriteLine("error");
break;
}
double total = price * amount;
Console.WriteLine(total);
}
else if (city == "Varna")
{
switch (product)
{
case "coffee":
price = 0.45;
break;
case "water":
price = 0.70;
break;
case "beer":
price = 1.10;
break;
case "sweets":
price = 1.35;
break;
case "peanuts":
price = 1.55;
break;
default:
Console.WriteLine("error");
break;
}
double total = price * amount;
Console.WriteLine(total);
}
else
{
Console.WriteLine("error");
}
}
}
}
Оправих го и го прие, просто трябваше да чета по-внимателно и търпеливо и да оправя променливите, явно не мога да умножавам десетични и реални числа (double * decimal). Явно трябва да разбера че програмирането не е съвсем точна наука и има флуктоации, надявам се като понапредна да почна повече да разбирам особеностите и от какво произлизат. Благодаря за помоща отговорите и проявеното търпение.
usiнg System;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
string product = Console.ReadLine();
string city = Console.ReadLine();
decimal amount = decimal.Parse(Console.ReadLine());
decimal price = 0.0m;
// Main variable definition
if (city == "Sofia")
{
switch (product)
{
case "coffee":
price = 0.50m;
break;
case "water":
price = 0.80m;
break;
case "beer":
price = 1.20m;
break;
case "sweets":
price = 1.45m;
break;
case "peanuts":
price = 1.60m;
break;
default:
Console.WriteLine("error");
break;
}
decimal total = price * amount;
Console.WriteLine(total);
}
else if (city == "Plovdiv")
{
switch (product)
{
case "coffee":
price = 0.40m;
break;
case "water":
price = 0.70m;
break;
case "beer":
price = 1.15m;
break;
case "sweets":
price = 1.30m;
break;
case "peanuts":
price = 1.50m;
break;
default:
Console.WriteLine("error");
break;
}
decimal total = price * amount;
Console.WriteLine(total);
}
else if (city == "Varna")
{
switch (product)
{
case "coffee":
price = 0.45m;
break;
case "water":
price = 0.70m;
break;
case "beer":
price = 1.10m;
break;
case "sweets":
price = 1.35m;
break;
case "peanuts":
price = 1.55m;
break;
default:
Console.WriteLine("error");
break;
}
decimal total = price * amount;
Console.WriteLine(total);
}
else
{
Console.WriteLine("error");
}
}
}
}