The MidpointRound.AwayFromZero overload is supposed to round the 5 up in a rounding situation.
EX: Math.Round(1.5, 1, MidpointRounding.AwayFromZero);
This rounds 1.5 to 2.
However, when I try Math.Round(1.025, 2, MidpointRounding.AwayFromZero); it rounds it down to 1.02. It is supposed to round up to 1.03 though.
Does anyone have any idea why this is happening? Thanks!
The value 1.025 cannot be represented exactly as the type double. Floating point numbers have that problem. See Why are floating point numbers inaccurate?.
When you write 1.025 as a double number, it will internally be a little bit smaller than 1.025. That's why the rounding delivers an unexpected value.
When dealing with money or other stuff where you want the value be exactly the same as displayed, use the type decimal instead of double:
decimal roundedValue = Math.Round(1.025m, 2, MidpointRounding.AwayFromZero);
Note that the m after the number turns the number into a literal of the decimal type.
Related
I have a problem to round a number to two decimal places.
I have the number 3106.4647771976413339683766317M.
The correct round to two decimal places is 3106.47, but using Math.Round(value, 2, MidpointRounding.AwayFromZero) the number is 3106.46.
The problem is the method look to third decimal place to round, but if it look to fourth decimal place will generate the correct number.
Someone has something like that?
Mathematically, the correct round to two decimal places is 3106.46.
What you probably want is a ceiling:
Math.Ceiling(3106.4647771976413339683766317M * 100) / 100
produces 3106.47. There is no version of Math.Ceiling accepting a number of decimal places, that's why there are multiplication and division.
In addition, note that there is a caveat in this expression:
Math.Round(value, 2, MidpointRounding.AwayFromZero)
Math.Round does not have a variant with three arguments, where the first one is a decimal. It works, because the value is implicitly converted to double. However, this is unwanted.
If you really want to round that way (more of a common mistake than actual rounding in the traditional sense) you can round up from the furthest right digit and move left one place at a time.
double numberToRound = 3106.4647771976413339683766317;
int placesToRoundTo = 2;
int smallestPlaceIndex = 24; // you would need to determine this value
for (int i = smallestPlaceIndex; i >= placesToRoundTo)
{
numberToRound = Math.Round(numberToRound, i, MidpointRounding.AwayFromZero);
}
There isn't a simple built-in method to do this because it isn't normal rounding.
I'm trying to convert Single to Double while maintaining the original value. I've found the following method:
Single f = 5.2F;
Double d1 = f; // 5.19999980926514
Double d2 = Double.Parse(f.ToString()); // 5.2 (correct)
Is this practice recommendable? I don't need an optimal method, but the intended value must be passed on to the double. Are there even consequences to storing a rounded value in a double?
You could use "decimal" instead of a string.
float f = 5.2F;
decimal dec = new decimal(f);//5.2
double d = (double)dec; //5.2
The conversion is exact. All the Single values can be represented by a Double value, because they are "built" in the same way, just with more possible digits. What you see as 5.2F is in truth 5.1999998092651368. If you go http://www.h-schmidt.net/FloatConverter/IEEE754.html and insert 5.2 you'll see that it has an exponent of 2^2 (so 4) and a mantissa of 1.2999999523162842. Now, if you multiply the two numbers you'll get 5.1999998092651368.
Single have a maximum precision of 7 digits, so .NET only shows 7 digits. With a little rounding 5.1999998092651368 is 5.2
If you know that your numbers are multiples of e.g. 0.01, I would suggest that you convert to double, round to the nearest integer, and subtract that to get the fractional residue. Multiply that by 100, round to the nearest integer, and then divide by 100. Add that to the whole-number part to get the nearest double representation to the multiple of 0.01 which is nearest the original number.
Note that depending upon where the float values originally came from, such treatment may or may not improve accuracy. The closest float value to 9000.02 is about 9000.019531, and the closest float value to 9000.021 is about 9000.021484f. If the values were arrived at by converting 9000.020 and 9000.021 to float, the difference between them should be about 0.01. If, however, they were arrived at by e.g. computing 9000f+0.019531f and 9000f+0.021484f, then the difference between them should be closer to 0.02. Rounding to the nearest 0.01 before the subtract would improve accuracy in the former case and degrade it in the latter.
I am facing problem while rounding the decimal value in C# using Math.Round(a, 2);
When I'm rounding 1.275 by 2 decimal points, the result is 1.27.
When I'm doing the same for 1.375, the result is 1.38.
Why is it not rounding 1.275 to 1.28?
Thanks
I cannot reproduce your problem:
Math.Round(1.275m, 2) => 1.28m
Math.Round(1.375m, 2) => 1.38m
I suspect that your claim that you use a decimal value is false, and that you use double value instead. double can't represent many decimal values exactly, so when you write 1.275, it's actually 1.27499... 1.375 is one of the few representable onces, so it's actually 1.375.
If your code cares about exact decimal representation, for example when you work on money, you must use decimal and not binary floating point such as double or float.
But even if you use decimal representation, rounding behaves unexpectedly for many users:
Math.Round(1.265m, 2) => 1.26m
Math.Round(1.275m, 2) => 1.28m
By default Math.Round uses MidpointRounding.ToEven, also known as Banker's round. This avoids accumulating a bias from always rounding up at .5.
You can use an overload of Round that takes a rounding mode, and set it to AwayFromZero to get the behaviour you expect.
Math.Round(1.275m, 2, MidpointRounding.AwayFromZero) => 1.28m
MSDN has this to say regarding this behavior:
Notes to Callers
Because of the loss of precision that can result from
representing decimal values as floating-point numbers or performing
arithmetic operations on floating-point values, in some cases the
Round(Double, Int32) method may not appear to round midpoint values to
the nearest even value in the digits decimal position. This is
illustrated in the following example, where 2.135 is rounded to 2.13
instead of 2.14. This occurs because internally the method multiplies
value by 10digits, and the multiplication operation in this case
suffers from a loss of precision.
public class Example
{
public static void Main()
{
double[] values = { 2.125, 2.135, 2.145, 3.125, 3.135, 3.145 };
foreach (double value in values)
Console.WriteLine("{0} --> {1}", value, Math.Round(value, 2));
}
}
// The example displays the following output:
// 2.125 --> 2.12
// 2.135 --> 2.13
// 2.145 --> 2.14
// 3.125 --> 3.12
// 3.135 --> 3.14
// 3.145 --> 3.14
If you have a Decimal value, it will correctly round 1.275 to 1.28.
If you have a Double value, it will not behave the same, because the value 1.275 can not be represented exactly. If you use the double value 1.275, it will actually be slightly smaller than the exact value 1.275, something like 1.2749999999999999.
When rounding that value, it will not be exacly between 1.27 and 1.28 but slightly closer to 1.27, so it will be rounded down instead of up.
This is a terrible hack, but try using Format. It inexplicably uses the rounding we're all used to.
Val(Format(2.25, "0.0")) returns 2.3
(OR)
Just for information: From .Net version 2.0 its possible to define the way the "0.5 cases" are rounded with a parameter MidpointRounding. It can be either ToEven or AwayFromZero. So "standard" rounding would be like this:
Math.Round(2.25, 1, MidpointRounding.AwayFromZero);
This would return value "2.3".
Format(1.275, "0.00"))
as suggested in this blog's comments: http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx
Which version of the .Net framework do you use? If it is above 1.1, you can use the midpointrounding and set it to AwayFromZero
Math.Round(1.275, 2, MidpointRounding.AwayFromZero);
http://msdn.microsoft.com/en-us/library/9s0xa85y%28v=vs.110%29.aspx
It's because your rounding a double, and not a decimal:
Console.WriteLine(Math.Round(1.275M, 2)); // outputs 1.28
Console.WriteLine(Math.Round(1.375M, 2)); // outputs 1.38
Decimal and doubles are very different
Expected behaviour as per the documentation.
For example, if decimals is equal to 1, 2.15 and 2.15000 are both
rounded to 2.2 because .05 and .05000 are both halfway between .1 and
.2, and .1 is odd. Similarly, if decimals is equal to 1, 2.05 and
2.05000 are both rounded to 2.0 because .05 and .05000 are both halfway between .0 and .1, and .0 is even. The behavior of this
method follows IEEE Standard 754, section 4. This kind of rounding is
sometimes called rounding to nearest, or banker's rounding. It
minimizes rounding errors that result from consistently rounding a
midpoint value in a single direction. To control the type of
rounding used by the Round(Decimal, Int32) method, call the
Decimal.Round(Decimal, Int32, MidpointRounding) overload.
From Math.Round(decimal, int). Try
Decimal.Round(a, 2, MidpointRounding.AwayFromZero);
I have the following code:
int a = Convert.ToInt32(4.5m);
int b = Convert.ToInt32(5.5m);
Console.WriteLine(a);
Console.WriteLine(b);
And here's the output:
4
6
Why does Convert.ToInt32 rounds decimal values to the nearest even number?
Convert is using rounding to nearest, or banker's rounding:
The behavior of this method follows IEEE Standard 754, section 4. This
kind of rounding is sometimes called rounding to nearest, or banker's
rounding. It minimizes rounding errors that result from consistently
rounding a midpoint value in a single direction.
To control the type of rounding used by the Round method, call the
Math.Round(Double, MidpointRounding) overload.
int a = (int)Math.Floor(4.5m);
int b = (int)Math.Floor(5.5m);
MSDN:
Or:
int a = decimal.ToInt32(4.5m);
int b = decimal.ToInt32(4.5m)
You can also just use the explicit int cast operator:
int a = (int) 4.5m;
int b = (int) 5.5m;
But read this note from MSDN:
This operator supports the explicit conversion of a Decimal to a Int32. The syntax for such explicit conversions is language-dependent, and individual language compilers can provide different implementations and return different results. The example illustrates the different return values when you explicitly convert a Decimal value to an Int32 value by using C# and Visual Basic. To perform a conversion that is independent of language, you can call the ToInt32 or the Convert.ToInt32(Decimal) method.
Math.Floor Method (Decimal)
Returns the largest integer less than or equal to the specified decimal number.
Note that decimal is bigger than int so if the value is bigger than int.MaxValue you get an OverflowException
Math.Round() allows you to choose
Console.WriteLine(Math.Round(4.5m, 0, MidpointRounding.ToEven)); //4
Console.WriteLine(Math.Round(5.5m, 0, MidpointRounding.ToEven)); //6
Console.WriteLine(Math.Round(4.5m, 0, MidpointRounding.AwayFromZero)); //5
Console.WriteLine(Math.Round(5.5m, 0, MidpointRounding.AwayFromZero)); //6
(And, as you would guess, default is ToEven)
It does that because that's how it's defined (see below for reason):
Returns: value, rounded to the nearest 32-bit signed integer. If value is
halfway between two whole numbers, the even number is returned; that
is, 4.5 is converted to 4, and 5.5 is converted to 6.
you'd have to use something like Math.Floor if you want different results.
The documentation for Math.Round, which does the same thing, states the reason:
The behavior of this method follows IEEE Standard 754, section 4. This
kind of rounding is sometimes called rounding to nearest, or banker's
rounding. It minimizes rounding errors that result from consistently
rounding a midpoint value in a single direction.
To control the type of rounding used by the Round(Decimal) method,
call the Math.Round(Decimal, MidpointRounding) overload.
From http://msdn.microsoft.com/en-us/library/93kx4xke
Return Value
Type: System.Int32 value, rounded to the nearest 32-bit signed
integer. If value is halfway between two whole numbers, the even
number is returned; that is, 4.5 is converted to 4, and 5.5 is
converted to 6.
I read something yesterday that when rounding occurs it rounds to the nearest even number, its called bankers rounding. You have to tell it how you want to round
EDIT: you asked for an explanation of why it rounds to the nearest even number.
say you have 10 numbers (this is an extreme case
1.5,
2.5,
3.5,
4.5,
5.5,
6.5,
7.5,
8.5,
9.5,
10.5
the sum = 60
if you round them all off first
the sum = 65 because they would all round up
if you bankers round them
the sum = 60
I want to round up double value in two decimal places in c# how can i do that?
double inputValue = 48.485;
after round up
inputValue = 48.49;
Related: c# - How do I round a decimal value to 2 decimal places (for output on a page)
This works:
inputValue = Math.Round(inputValue, 2);
Math.Round(inputValue, 2, MidpointRounding.AwayFromZero)
Another easy way is to use ToString with a parameter.
Example:
float d = 54.9700F;
string s = d.ToString("N2");
Console.WriteLine(s);
Result:
54.97
Use Math.Round
value = Math.Round(48.485, 2);
You should use
inputvalue=Math.Round(inputValue, 2, MidpointRounding.AwayFromZero)
Math.Round
Math.Round rounds a double-precision floating-point value to a
specified number of fractional digits.
MidpointRounding
Specifies how mathematical rounding methods should process a number
that is midway between two numbers.
Basically the function above will take your inputvalue and round it to 2 (or whichever number you specify) decimal places. With MidpointRounding.AwayFromZero when a number is halfway between two others, it is rounded toward the nearest number that is away from zero. There is also another option you can use that rounds towards the nearest even number.
you can try one from below.there are many way for this.
1.
value=Math.Round(123.4567, 2, MidpointRounding.AwayFromZero) //"123.46"
2.
inputvalue=Math.Round(123.4567, 2) //"123.46"
3.
String.Format("{0:0.00}", 123.4567); // "123.46"
4.
string.Format("{0:F2}", 123.456789); //123.46
string.Format("{0:F3}", 123.456789); //123.457
string.Format("{0:F4}", 123.456789); //123.4568
Use an interpolated string, this generates a rounded up string:
var strlen = 6;
$"{48.485:F2}"
Output
"48.49"
I think all these answers are missing the question. The problem was to "Round UP", not just "Round". It is my understanding that Round Up means that ANY fractional value about a whole digit rounds up to the next WHOLE digit. ie: 48.0000000 = 48 but 25.00001 = 26. Is this not the definition of rounding up? (or have my past 60 years in accounting been misplaced?