This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is floating point arithmetic in C# imprecise?
Why can't decimal numbers be represented exactly in binary?
I dont understand why, this formula works untill Scrap = 51, Rec Should be 17 but instead is 16.99.
Scrap = int.Parse(textBoxS.Text);
for (counter = 0; counter < Scrap; textBoxRec.Text = Rec.ToString() )
{
if (Rec == (int)Rec + 0.66)
{
Rec = (int)Rec + 1;
counter++;
}
else
{
Rec = Rec + 0.33;
counter++;
}
}
Comparing floating point numbers by == is never a good idea.
double d1 = 16.0 + 0.33 + 0.33
double d2 = 16.0 + 0.66
Then d1 != d2, since 0.33 does not have an exact representation as a double, since double is a binary floating point number and probably the double representation of 0.66 is different from two times the double representation of 0.33.
Use decimal.
And try to improve your code. Increasing the counter inside the loop and using the third position in the head of the for loop for a different purpose is horrible style, in my opinion.
I assume that Rec is double and its initial value is 0. than
Insted of
if (Rec == (int)Rec + 0.66)
use
if (Math.Abs(Rec-(int)Rec-0.66) < 0.001)
Simple solution: change Rec from double to decimal. If so, you also have to change 0.66 to 0.66m and 0.33 to 0.33m.
Rec == (int)Rec + 0.66 can be false even if numbers are "equal". It is related to floating point numbers binary representation. Floating point numbers must be compared in slightly different way:
if (Math.Abs(Rec - ((int) Rec + 0.66)) < epsilon) ...
where epsilon is some small value, in this case 0.1 will be enough.
Related
I wanted to ask a question about a calculation I had today in C#.
double expenses = (pricePen + priceMark + priceLitres) - discount / 100*(pricePen + priceMark + priceLitres); //Incorrect
double expenses = (pricePen + priceMark + priceLitres) - (pricePen + priceMark + priceLitres)* discount/100; //Correct
So as you can see at the end of the equation I had to multiply the brackets by the integer named "discount", which is obviously a discount percentage.
When I change the places of that value whether it would be in front of the brackets or behind the brackets the answer will always be different, but in Maths I even checked myself that I should get the same answer even if the value is placed in front of the brackets to multiply or placed behind the brackets to multiply again, but C# doesn't think so.
I wanted to ask people, how does C# actually calculate this and why am I getting different results at the end? (Result should be 28.5, not 38)
[Data: pricePen = 11.6; priceMark = 21.6; priceLitres = 4.8; discount = 25;]
(I know that the question is irrelevant.)
In first line after dividing by 100 the result is in an integer. For that the rest of division get lost. So the multiplication has a lower result.
In second line the multiplication has the correct result and the rest of devision is lower than one.
So I know its already answered but if you want to learn more about divisions with int
here it is:
for example:
float value = 3/4 you would expect it to be 0.75 but that's not the case.
Because when the Compiler goes through the values 3 and 4 he makes des Literal of the highest data type - in this case (int)-.
That means the result of this division will be "0".75 because int has no floating numbers and just cuts it off. Then the program just takes that value and puts it in the float value ...
so the result will be
"3/4" 0 ->"float value" 0.0 = 0.0
Some guys before me already told you the solution to that problem like making one divisor to float with .0
float value = 3.0/4
or you can tell the Compiler to store the value in a float Literal with the (float) "command"
float value = (float) 3/4
I hope it helped you explain why you did that :)
To avoid these problems makes sure you are doing math with floating point types, and not int types. In your case discount is an int and thus
x * (discount / 100) = x * <integer>
Best to define a function to do the calculation which forces the type
double DiscountedPrice(double price, double discount)
{
return price - (discount/100) * price;
}
and then call it as
var x = DiscountedPrice( pricePen + priceMark + priceLitres, 15);
In the above scenario, the compiler will force the integer 15 to be converted into an double as a widening conversion (double has more digits than integer).
I want to extract N number of decimal points after the value without doing round up.
Below is the example :
string val = null;
int numberOfDigitsAfterDecimalPoint = 2;
double val1 = 56423747.61;
double val2 = 56423996.57;
val = ((56423747.61 / 56423996.57) * 100).ToString(); //99.9995587692912
val = String.Format("{0:n" + numberOfDigitsAfterDecimalPoint.ToString() + "}", (100 * Convert.ToDecimal(val)) / 100); //100.00
But problem here is it is rounding up and I am getting 100.00 which I don't want because I want exact value with decimal point i.e 99.99 without any kind of round up.
I searched and came to conclusion(my thinking) that best way to handle this is by extracting number of digits after decimal point with substring method but still I am not sure that whether i am thinking in wrong or right way.
Expected output with numberOfDigitsAfterDecimalPoint = 2 :
99.99
Update
I am not having a fixed value to get after decimal point because it is dependent on numberOfDigitsAfterDecimalPoint variable. Apart from that can have very large value based on which I am calculating val; that is why I was thinking to use substring function in which I won't have any problem related to round off, as oppose to mathematical calculation or math function.
How can I do this in efficient way without compromising any value?
This question already has answers here:
Why am I getting the wrong result when using float? [duplicate]
(4 answers)
Float is converting my values
(4 answers)
Closed 9 years ago.
The result must be 806603.77 but why I get 806603.8 ?
float a = 855000.00f;
float b = 48396.23f;
float res = a - b;
Console.WriteLine(res);
Console.ReadKey();
You should use decimal instead because float has 32-bit with 7 digit precision only that is why the result differs, on other hand decimal has 128-bit with 28-29 digit precision.
decimal a = 855000.00M;
decimal b = 48396.23M;
decimal res = a - b;
Console.WriteLine(res);
Console.ReadKey();
Output: 806603.77
A float (also called System.Single) has a precision equivalent to approximately seven decimal figures. Your res difference needs eight significant decimal digits. Therefore it is to be expected that there is not enough precision in a float.
ADDITION:
Some extra information: Near 806,000 (806 thousand), a float only has four bits left for the fractional part. So for res it will have to choose between
806603 + 12/16 == 806603.75000000, and
806603 + 13/16 == 806603.81250000
It chooses the first one since it's closest to the ideal result. But both of these values are output as "806603.8" when calling ToString() (which Console.WriteLine(float) does call). A maximum of 7 significant decimal figures are shown with the general ToString call. To reveal that two floating-point numbers are distinct even though they print the same with the standard formatting, use the format string "R", for example
Console.WriteLine(res.ToString("R"));
Because float has limited precision (32 bits). Use double or decimal if you want more precision.
Please be aware that just blindly using Decimal isn't good enough.
Read the link posted by Oded: What Every Computer Scientist Should Know About Floating-Point Arithmetic
Only then decide on the appropriate numeric type to use.
Don't fall into the trap of thinking that just using Decimal will give you exact results; it won't always.
Consider the following code:
Decimal d1 = 1;
Decimal d2 = 101;
Decimal d3 = d1/d2;
Decimal d4 = d3*d2; // d4 = (d1/d2) * d2 = d1
if (d4 == d1)
{
Console.WriteLine("Yay!");
}
else
{
Console.WriteLine("Urk!");
}
If Decimal calculations were exact, that code should print "Yay!" because d1 should be the same as d4, right?
Well, it doesn't.
Also be aware that Decimal calculations are thousands of times slower than double calculations. They are not always suitable for non-currency calculations (e.g. calculating pixel offsets or physical things such as velocities, or anything involving transcendental numbers and so on).
I understand that floating point arithmetic as performed in modern computer systems is not always consistent with real arithmetic. I am trying to contrive a small C# program to demonstrate this. eg:
static void Main(string[] args)
{
double x = 0, y = 0;
x += 20013.8;
x += 20012.7;
y += 10016.4;
y += 30010.1;
Console.WriteLine("Result: "+ x + " " + y + " " + (x==y));
Console.Write("Press any key to continue . . . "); Console.ReadKey(true);
}
However, in this case, x and y are equal in the end.
Is it possible for me to demonstrate the inconsistency of floating point arithmetic using a program of similar complexity, and without using any really crazy numbers? I would like, if possible, to avoid mathematically correct values that go more than a few places beyond the decimal point.
double x = (0.1 * 3) / 3;
Console.WriteLine("x: {0}", x); // prints "x: 0.1"
Console.WriteLine("x == 0.1: {0}", x == 0.1); // prints "x == 0.1: False"
Remark: based on this don't make the assumption that floating point arithmetic is unreliable in .NET.
Here's an example based on a prior question that demonstrates float arithmetic not working out exactly as you would think.
float f = (13.45f * 20);
int x = (int)f;
int y = (int)(13.45f * 20);
Console.WriteLine(x == y);
In this case, false is printed to the screen. Why? Because of where the math is performed versus where the cast to int is happening. For x, the math is performed in one statement and stored to f, then it is being cast to an integer. For y, the value of the calculation is never stored before the cast. (In x, some precision is lost between the calculation and the cast, not the case for y.)
For an explanation behind what's specifically happening in float math, see this question/answer. Why differs floating-point precision in C# when separated by parantheses and when separated by statements?
My favourite demonstration boils down to
double d = 0.1;
d += 0.2;
d -= 0.3;
Console.WriteLine(d);
The output is not 0.
Try making it so the decimal is not .5.
Take a look at this article here
http://floating-point-gui.de/
try sum VERY big and VERY small number. small one will be consumed and result will be same as large number.
Try performing repeated operations on an irrational number (such as a square root) or very long length repeating fraction. You'll quickly see errors accumulate. For instance, compute 1000000*Sqrt(2) vs. Sqrt(2)+Sqrt(2)+...+Sqrt(2).
The simplest I can think of right now is this:
class Test
{
private static void Main()
{
double x = 0.0;
for (int i = 0; i < 10; ++i)
x += 0.1;
Console.WriteLine("x = {0}, expected x = {1}, x == 1.0 is {2}", x, 1.0, x == 1.0);
Console.WriteLine("Allowing for a small error: x == 1.0 is {0}", Math.Abs(x - 1.0) < 0.001);
}
}
I suggest that, if you're truly interested, you take a look any one of a number of pages that discuss floating point numbers, some in gory detail. You will soon realize that, in a computer, they're a compromise, trading off accuracy for range. If you are going to be writing programs that use them, you do need to understand their limitations and problems that can arise if you don't take care. It will be worth your time.
double is accurate to ~15 digits. You need more precision to really start hitting problems with only a few floating point operations.
Ex, I have number 345.38, 2323.805555, 21.3333. I want to get the number after the decimal and round it up.
345.38 --> 4
2323.805555 --> 8
21.3333 --> 3
multiply by 10
ceiling (always rounds up, use 'round' to round down if lower than 0.5)
find the result of modding by 10
Like:
float myFloat = 123.38f;
float myBiggerFloat = Math.Ceiling(myFloat * 10.0f);
int theAnswer = ((int)myBiggerFloat % 10);
Or just ask for help for your homework on SO, either way seems to work.
This avoids potential overflow issues:
decimal value;
string[] sep = new[] { NumberFormatInfo.CurrentInfo.NumberDecimalSeparator };
String.Format("{0:0.0}", Math.Round(value, 1)).Split(sep, StringSplitOptions.None)[1][0];
This avoids string conversions and overflow issues:
decimal value;
decimal absValue = Math.Abs(value);
decimal fraction = absValue - Math.Floor(absValue);
int lastDigit = Convert.ToInt32(10 * Math.Round(fraction, 1));
If you just want the digit immediately following the decimal...couldn't you do something like this?
float value;
int digit = (int)(((value % 1) * 10) + 0.5)
Get the fractional part, multiply by ten, and round:
double n = 345.38;
int digit = (int)Math.Round((n - Math.Floor(n)) * 10);
This avoids any overflow issues, as the result is already down to one digit when cast to an int.
I have verified that this gives the desired result for your examples.
This whole overflow discussion is a little academic, and most likely not the intention of your homework. But should you want to solve that problem:
decimal value = -0.25m;
decimal fractionalPart = Math.Abs(value - Math.Truncate(value));
int digit = (int)Math.Round(10 * fractionalPart, MidpointRounding.AwayFromZero);
Edit: after reading your question again, I noticed that numbers shouldn't always be rounded up like my original answer. However, most people using Math.Round here use the default banker's rounding (to an even number). It depends if you intended -0.25 to result in 2 or 3. The way I'm reading your description, it should be 3 like in this example.
float myNum = 10.11;
char c = myNum[myNum.ToString().IndexOf(".") + 1];