Why does the decimal 2.5M round to 2? [duplicate] - c#

This question already has answers here:
Why does Math.Round(2.5) return 2 instead of 3?
(15 answers)
Closed 6 years ago.
I must be missing some subtlety of .NET rounding. So I am looking at this example:
decimal num = 2.5M;
var result = Math.Round(num);
Why is result = 2? (I would have expected 3 since it should round up)

See MSDN:
Decimal Math.Round(Decimald)
Rounds a decimal value to the nearest integer, and rounds midpoint
values to the nearest even number (example).
"Midpoint" here means .5; the even number in your case is 2. If you rounded 3.5 this way, it would result in 4.
If you want to use "away from zero" rounding instead, you can use the System.MidpointRounding.AwayFromZero enum:
decimal d = 2.5M;
decimal roundedD = Math.Round(d, MidpointRounding.AwayFromZero); // results in 3
Regarding why it uses midpoint rounding (AKA "banker's rounding") by default instead of "away from zero" rounding, see this answer. Supposedly it's a better algorithm (i.e. more efficient over many iterations).

If you want classic rounding use
decimal num = 2.5M;
var result = Math.Round(num,0, MidpointRounding.AwayFromZero);
Please see https://msdn.microsoft.com/en-us/library/system.math.round(v=vs.110).aspx for details

Related

float/double Math.Round in C# [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Rounding of float values
(2 answers)
Difference between decimal, float and double in .NET?
(18 answers)
Closed 4 years ago.
float ff = (float)31.15;
double dd = 31.15;
var frst = Math.Round(ff, 1, MidpointRounding.AwayFromZero);
var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);
frst: 31.1
drst: 31.2
Can someone explain why?
Well, Math.Round wants double, not float, that's why
Math.Round(ff, 1, MidpointRounding.AwayFromZero);
equals to
Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);
and if we inspect (double)ff value
Console.Write(((double)ff).ToString("R"));
we'll see round up errors in action
31.149999618530273
Finally, Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1 as expected
In floating point, all numbers are represented internally as fractions where the denominator is a power of 2.
(This is a similar way to how decimals are actually fractions with power-of-10 denominators. So 31.15 is just a way of writing the fraction 3115/100)
In floating point, 31.15 must be represented internally as a binary number. The closest binary fraction is: 1111.1001001100110011001100110011001100110011001100110011001100...repeating
The 1100 recurs (repeats forever), and so the number will be truncated depending on whether it is stored in a double or a float. In a float it is truncated to 24 digits, and in a double to 53.
Exact: 1111.100100110011001100110011001100110011001100110011001100110011001100...forever
Float: 1111.10010011001100110011
Double: 1111.1001001100110011001100110011001100110011001100110
Therefore you can see that the double that this number converts to, is actually slightly larger than the float it converts to. So it is clear that it won't necessarily round to the same number, since it is not the same number to begin with.

Math.Sqrt(2/3) returns 0 [duplicate]

This question already has answers here:
Why does integer division in C# return an integer and not a float?
(8 answers)
Closed 6 years ago.
I am really confused why this is happening, my code:
double x = Math.Sqrt(2/3);
MessageBox.Show(x.ToString());
Displays 0.
The answer is
0.8164, I know I will also have to use Math.Round to round this up, but for the moment the issue is I'm getting 0
The problem is caused by automatic integer evaluation of the numbers. Use:
double x = Math.Sqrt(2f/3f);
MessageBox.Show(x.ToString());
2 / 3 is an integer operation, what you want is 2.0 / 3 which means I want to use floating point numbers.
What you consider an Intereger is different from what you know from Maths. In programming languages it means that a result of an int-operation is allways an integer in itself.
In your example 2 / 3 is an integer-operation which means the result is rounded down to the nearest integer, which is zero. To avoid this indicate that at least one of your operands should be treates as some floating-point value, either using 2.0 or 2f (alternativly 3.0 or 3f).

Rounding bug in c#? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
I'm having problems with a Rounding issue in c#. I would like to round the result of a calculation up to 4 decimals (awayfromzero). If I use Math.Round(variable,...) it rounds down, if I enter the result manually, it rounds up.. I have no idea why..
What am I doing wrong? The result of the below code is:
Rounded: 591.24575 591.2457 - 591.2458
double number1 = 1136.81;
double number2 = 4.00;
double number3 = 2182.257;
double result = (number1 * number2 - number3) / 4;
Console.WriteLine("Rounded: " +result+" " + Math.Round(result, 4, MidpointRounding.AwayFromZero) + " - " + Math.Round(591.24575, 4, MidpointRounding.AwayFromZero));
Console.ReadLine();
If you use my DoubleConverter, you can see the exact value of result:
Console.WriteLine(DoubleConverter.ToExactString(result));
That prints:
591.2457499999999299689079634845256805419921875
... which rounds to 591.2457 when rounded to 4 decimal places. When you just print result, it's printing it already rounded to a certain number of decimal places, which can affect the result if you then (mentally) rounded to 4 DP.
You can see this without any of the "normal" oddities of binary floating point. Consider this code:
decimal exact = 1.2345m;
decimal rounded2 = Math.Round(exact, 2, MidpointRounding.AwayFromZero);
decimal rounded3 = Math.Round(exact, 3, MidpointRounding.AwayFromZero);
decimal rounded3Then2 = Math.Round(rounded3, 2, MidpointRounding.AwayFromZero);
Console.WriteLine(rounded2); // 1.23
Console.WriteLine(rounded3); // 1.235
Console.WriteLine(rounded3Then2); // 1.24
In your code you weren't actually performing the "two roundings" - but you were mentally doing so by taking the printed value of result (591.24575) and assuming you could take that to be accurate in order to round it further.
result is not exactly 591.24575, it is some number that is very close to 591.24575 but it is just slightly smaller, something along the lines of 591.24574999999999, as a result of the fact that certain numbers that have a finite number of digits in base 10 cannot be represented with a finite number of digits in base 2. When you set the number exactly you are avoiding ever having a double set to one of those values as an intermediate value of your calculations.
If you are dealing with numbers that have a known fixed number of base 10 digits and it's important that you not have these precision errors than it may be appropriate to use Decimal in this context.
result doesn't have the value you think it does, it's being truncated by putting it in a string representation. As for why that is, read What Every Computer Scientist Should Read About Floating Point
Take a look while debugging:
result: 591.24574999999993
result.ToString(): "591,24575"

c# double - why is the answer always 0? [duplicate]

This question already has answers here:
Why returns C# Convert.ToDouble(5/100) 0.0 and not 0.05
(7 answers)
Closed 8 years ago.
I have a double that when assigned is always coming back as 0.0, but should not happen.
The code I have is
double test = (27096140 / 27216140);
The answer to this should be 0.9955....
I am not using the double primitive type correctly?
Cheers
Edit
Of course, I was using int and no floating points.
Knew it would be a matter of common sense.
You are using integer division, you should use floating-point division:
double test = (27096140.0 / 27216140);
You are actually performing integer division here because the 2 numbers are whole. That forces the result of the calculation to be int which truncates the precision so you end up with 0.
You need to tell the compiler you are actually working with floating-point numbers and not int's, just adding a floating point to one of the numbers should fix this e.g.
double test = (27096140.0 / 27216140);
Alternatively, you could actually declare the numbers as doubles
double a = 27096140;
double b = 27216140;
double test = (a / b);
Or even cast the number in the calculation
double test = ((double)27096140 / 27216140)
Beacuse you're using integers instead of doubles. Use:
double test = (27096140.0d / 27216140.0d);
The numbers 27096140 and 27216140 are ints, so the result of the division is also an int: 0.
Then this is cast to a double: 0.0

How to round to a specific decimal accuracy? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Round a double to 2 significant figures after decimal point
I have a value var i = 0.69999980926513672. I need to round this value to 0.7 is there a built-in method that will do this?
Use one of:
System.Math.Round (i, 1, MidpointRounding.ToEven);
System.Math.Round (i, 1, MidpointRounding.AwayFromZero);
The difference is how it handles numbers that are equidistant to the rounding point (e.g., 0.65 in your case could either go to 0.7 or 0.6).
Here is a answer I gave to another question which holds much more information.
You are looking for the Math.Round method.
//first param is number to round
//second param is the accuracy to use in the rounding (number of decimal places)
Math.Round(i, 2)
Console.WriteLine(System.Math.Round(0.69999980926513672d, 1));
-- edit
wow, you blink and there are 5 other answers!
http://msdn.microsoft.com/en-us/library/system.math.round%28VS.71%29.aspx
Use the Math.Round method:
double i = 0.69999980926513672;
double result = Math.Round(i, 2);

Categories

Resources