How can I multiply two decimals and round the result down to 2 decimal places?
For example if the equation is 41.75 x 0.1 the result will be 4.175. If I do this in c# with decimals it will automatically round up to 4.18. I would like to round down to 4.17.
I tried using Math.Floor but it just rounds down to 4.00. Here is an example:
Math.Floor (41.75 * 0.1);
The Math.Round(...) function has an Enum to tell it what rounding strategy to use. Unfortunately the two defined won't exactly fit your situation.
The two Midpoint Rounding modes are:
AwayFromZero - When a number is halfway between two others, it is rounded toward the nearest number that is away from zero. (Aka, round up)
ToEven - When a number is halfway between two others, it is rounded toward the nearest even number. (Will Favor .16 over .17, and .18 over .17)
What you want to use is Floor with some multiplication.
var output = Math.Floor((41.75 * 0.1) * 100) / 100;
The output variable should have 4.17 in it now.
In fact you can also write a function to take a variable length as well:
public decimal RoundDown(decimal i, double decimalPlaces)
{
var power = Convert.ToDecimal(Math.Pow(10, decimalPlaces));
return Math.Floor(i * power) / power;
}
public double RoundDown(double number, int decimalPlaces)
{
return Math.Floor(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}
As of .NET Core 3.0 and the upcoming .NET Framework 5.0 the following is valid
Math.Round(41.75 * 0.1, 2, MidpointRounding.ToZero)
There is no native support for precision floor/ceillin in c#.
You can however mimic the functionality by multiplying the number, the floor, and then divide by the same multiplier.
eg,
decimal y = 4.314M;
decimal x = Math.Floor(y * 100) / 100; // To two decimal places (use 1000 for 3 etc)
Console.WriteLine(x); // 4.31
Not the ideal solution, but should work if the number is small.
One more solution is to make rounding toward zero from rounding away from zero.
It should be something like this:
static decimal DecimalTowardZero(decimal value, int decimals)
{
// rounding away from zero
var rounded = decimal.Round(value, decimals, MidpointRounding.AwayFromZero);
// if the absolute rounded result is greater
// than the absolute source number we need to correct result
if (Math.Abs(rounded) > Math.Abs(value))
{
return rounded - new decimal(1, 0, 0, value < 0, (byte)decimals);
}
else
{
return rounded;
}
}
This is my Float-Proof Round Down.
public static class MyMath
{
public static double RoundDown(double number, int decimalPlaces)
{
string pr = number.ToString();
string[] parts = pr.Split('.');
char[] decparts = parts[1].ToCharArray();
parts[1] = "";
for (int i = 0; i < decimalPlaces; i++)
{
parts[1] += decparts[i];
}
pr = string.Join(".", parts);
return Convert.ToDouble(pr);
}
}
I've found that the best method is to use strings; the binary vagaries of Math tend to get things wrong, otherwise. One waits for .Net 5.0 to make this fact obsolete. No decimal places is a special case: you can use Math.Floor for that. Otherwise, we ToString the number with one more decimal place than is required, then parse that without its last digit to get the answer:
/// <summary>
/// Truncates a Double to the given number of decimals without rounding
/// </summary>
/// <param name="D">The Double</param>
/// <param name="Precision">(optional) The number of Decimals</param>
/// <returns>The truncated number</returns>
public static double RoundDown(this double D, int Precision = 0)
{
if (Precision <= 0) return Math.Floor(D);
string S = D.ToString("0." + new string('0', Precision + 1));
return double.Parse(S.Substring(0, S.Length - 1));
}
If you want to round down any double to specific decimal places, if doesn´t matter if is the midpoint, you can use:
public double RoundDownDouble(double number, int decimaPlaces)
{
var tmp = Math.Pow(10, decimaPlaces);
return Math.Truncate(number * tmp) / tmp;
}
Related
How can I multiply two decimals and round the result down to 2 decimal places?
For example if the equation is 41.75 x 0.1 the result will be 4.175. If I do this in c# with decimals it will automatically round up to 4.18. I would like to round down to 4.17.
I tried using Math.Floor but it just rounds down to 4.00. Here is an example:
Math.Floor (41.75 * 0.1);
The Math.Round(...) function has an Enum to tell it what rounding strategy to use. Unfortunately the two defined won't exactly fit your situation.
The two Midpoint Rounding modes are:
AwayFromZero - When a number is halfway between two others, it is rounded toward the nearest number that is away from zero. (Aka, round up)
ToEven - When a number is halfway between two others, it is rounded toward the nearest even number. (Will Favor .16 over .17, and .18 over .17)
What you want to use is Floor with some multiplication.
var output = Math.Floor((41.75 * 0.1) * 100) / 100;
The output variable should have 4.17 in it now.
In fact you can also write a function to take a variable length as well:
public decimal RoundDown(decimal i, double decimalPlaces)
{
var power = Convert.ToDecimal(Math.Pow(10, decimalPlaces));
return Math.Floor(i * power) / power;
}
public double RoundDown(double number, int decimalPlaces)
{
return Math.Floor(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}
As of .NET Core 3.0 and the upcoming .NET Framework 5.0 the following is valid
Math.Round(41.75 * 0.1, 2, MidpointRounding.ToZero)
There is no native support for precision floor/ceillin in c#.
You can however mimic the functionality by multiplying the number, the floor, and then divide by the same multiplier.
eg,
decimal y = 4.314M;
decimal x = Math.Floor(y * 100) / 100; // To two decimal places (use 1000 for 3 etc)
Console.WriteLine(x); // 4.31
Not the ideal solution, but should work if the number is small.
One more solution is to make rounding toward zero from rounding away from zero.
It should be something like this:
static decimal DecimalTowardZero(decimal value, int decimals)
{
// rounding away from zero
var rounded = decimal.Round(value, decimals, MidpointRounding.AwayFromZero);
// if the absolute rounded result is greater
// than the absolute source number we need to correct result
if (Math.Abs(rounded) > Math.Abs(value))
{
return rounded - new decimal(1, 0, 0, value < 0, (byte)decimals);
}
else
{
return rounded;
}
}
This is my Float-Proof Round Down.
public static class MyMath
{
public static double RoundDown(double number, int decimalPlaces)
{
string pr = number.ToString();
string[] parts = pr.Split('.');
char[] decparts = parts[1].ToCharArray();
parts[1] = "";
for (int i = 0; i < decimalPlaces; i++)
{
parts[1] += decparts[i];
}
pr = string.Join(".", parts);
return Convert.ToDouble(pr);
}
}
I've found that the best method is to use strings; the binary vagaries of Math tend to get things wrong, otherwise. One waits for .Net 5.0 to make this fact obsolete. No decimal places is a special case: you can use Math.Floor for that. Otherwise, we ToString the number with one more decimal place than is required, then parse that without its last digit to get the answer:
/// <summary>
/// Truncates a Double to the given number of decimals without rounding
/// </summary>
/// <param name="D">The Double</param>
/// <param name="Precision">(optional) The number of Decimals</param>
/// <returns>The truncated number</returns>
public static double RoundDown(this double D, int Precision = 0)
{
if (Precision <= 0) return Math.Floor(D);
string S = D.ToString("0." + new string('0', Precision + 1));
return double.Parse(S.Substring(0, S.Length - 1));
}
If you want to round down any double to specific decimal places, if doesn´t matter if is the midpoint, you can use:
public double RoundDownDouble(double number, int decimaPlaces)
{
var tmp = Math.Pow(10, decimaPlaces);
return Math.Truncate(number * tmp) / tmp;
}
I am trying to figure out what the best way is to parse a decimal value. I am currently using Math.Round, but that does not seem to work for the input data.
I want to be able to get the integer part and then the first digit after the decimal.
var value = 25.987817685360218441503885773M;
return Math.Round(value, 1);
returns 26 but I would like to return 25.9.
Presuming that you want to "round" it to 25.9 not to 26.9, you have to do it manually.
var number = 25.9877;
var rounded = Convert.ToDouble(Convert.ToInt32(number*10))/10;
And, of course, this is not rounding, this is just chopping off the decimals.
Edit:
Math.Round has an overload for that:
System.Math.Round (n, 2, MidpointRounding.ToEven);
See Math.Round Method
You are rounding which will obviously round at the end. What you want to do is truncate the number. Here is a method that will accomplish what you want:
public decimal TruncateDecimal(decimal value, int precision)
{
decimal step = (decimal)Math.Pow(10, precision);
int tmp = (int)Math.Truncate(step * value);
return tmp / step;
}
You are rounding to the first decimal, but 25.98 rounds UP. Which means 8 is >=5 and makes 9 become 0 and carry the one to 5. ie 5+1. Thus you are getting 26.
Since there at least to my knowledge is no working solution here which does what the OP wants.
// .NET has no build in power function for decimals
decimal Pow(decimal value, int exp)
{
if (exp < 0)
return 1/Pow(value, -exp);
if (exp == 0)
return 1;
else if (exp % 2 == 0)
return Pow(value * value, exp / 2);
else return
value * Pow(value, exp - 1);
}
// Rounds a number to decimals decimals, ie 1 => 1 decimal, -2 => whole hundreds
public decimal Truncate(decimal number, int decimals)
{
var factor = 1 / Pow(10, decimals);
return number - (number % factor);
}
Do keep in mind though that this is not rounding, this is some weird form of truncating.
I have tried using Math.Round & MidpointRounding. This does not appear to do what I need.
Example:
52.34567 rounded to 2 decimals UP = 52.35
1.183 rounded to 2 decimals DOWN = 1.18
Do I need to write a custom function?
Edit:
I should have been more specific.
Sometimes I need a number like 23.567 to round DOWN to 23.56.
In this scenario...
Math.Round(dec, 2, MidpointRounding.AwayFromZero) gives 23.57
Math.Round(dec, 2, MidpointRounding.ToEven) gives 23.57
Decimals up to 9 decimal places could come out and need to be rounded to 1, 2, 3 or even 4 decimal places.
Try using decimal.Round():
decimal.Round(x, 2)
Where x is your value and 2 is the number of decimals you wish to keep.
You can also specify whether .5 rounds up or down by passing third parameter:
decimal.Round(x, 2, MidpointRounding.AwayFromZero);
EDIT:
In light of the new requirement (i.e. that numbers are sometimes rounded down despite being greater than "halfway" to the next interval), you can try:
var pow = Math.Pow(10, numDigits);
var truncated = Math.Truncate(x*pow) / pow;
Truncate() lops off the non-integer portion of the decimal. Note that numDigits above should be how many digits you want to KEEP, not the total number of decimals, etc.
Finally, if you want to force a round up (truncation really is a forced round-down), you would just add 1 to the result of the Truncate() call before dividing again.
Try using Math.Ceiling (up) or Math.Floor (down). e.g Math.Floor(1.8) == 1.
Assuming you're using the decimal type for your numbers,
static class Rounding
{
public static decimal RoundUp(decimal number, int places)
{
decimal factor = RoundFactor(places);
number *= factor;
number = Math.Ceiling(number);
number /= factor;
return number;
}
public static decimal RoundDown(decimal number, int places)
{
decimal factor = RoundFactor(places);
number *= factor;
number = Math.Floor(number);
number /= factor;
return number;
}
internal static decimal RoundFactor(int places)
{
decimal factor = 1m;
if (places < 0)
{
places = -places;
for (int i = 0; i < places; i++)
factor /= 10m;
}
else
{
for (int i = 0; i < places; i++)
factor *= 10m;
}
return factor;
}
}
Example:
Rounding.RoundDown(23.567, 2) prints 23.56
For a shorter version of the accepted answer, here are the RoundUp and RoundDown functions that can be used:
public double RoundDown(double number, int decimalPlaces)
{
return Math.Floor(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}
public double RoundUp(double number, int decimalPlaces)
{
return Math.Ceiling(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}
Complete code with result.
double a = Math.Round(128.5, 0, MidpointRounding.AwayFromZero);
Result is 129
The Math class gives you methods to use to round up and down, they are Math.Ceiling() and Math.Floor() respectively. They work like Math.Round(), but they have a particularity, they only receive a value and round them to only the entire part.
So you need to use Math.Pow() to multiply the value by 10 to the n-esimal units you need to round power and then you need to divide by the same multiplied value.
Is important that you note, that the input parameters of the Math.Pow() method are double, so you need to convert them to double.
For example:
When you want to round up the value to 3 decimals (supposing value type is decimal):
double decimalsNumber = 3;
decimal valueToRound = 1.1835675M;
// powerOfTen must be equal to 10^3 or 1000.
double powerOfTen = Math.Pow(10, decimalsNumber);
// rounded must be equal to Math.Ceiling(1.1835675 * 1000) / 1000
decimal rounded = Math.Ceiling(valueToRound * (decimal)powerOfTen) / (decimal)powerOfTen;
Result: rounded = 1.184
When you want to round down the value to 3 decimals (supposing value type is decimal):
double decimalsNumber = 3;
decimal valueToRound = 1.1835675M;
// powerOfTen must be equal to 10^3 or 1000.
double powerOfTen = Math.Pow(10, decimalsNumber);
// rounded must be equal to Math.Floor(1.1835675 * 1000) / 1000
decimal rounded = Math.Floor(valueToRound * (decimal)powerOfTen) / (decimal)powerOfTen;
Result: rounded = 1.183
To reference how to use them more specificaly and to get more information and about both methods you can see these pages from the oficial MSDN Microsoft site:
Math Class
Math.Pow Method (Double, Double)
Math.Floor Method (Decimal)
Math.Floor Method (Double)
Math.Ceiling Method (Decimal)
Math.Ceiling Method (Double)
try this custom rounding
public int Round(double value)
{
double decimalpoints = Math.Abs(value - Math.Floor(value));
if (decimalpoints > 0.5)
return (int)Math.Round(value);
else
return (int)Math.Floor(value);
}
Maybe this?
Math.Round(dec + 0.5m, MidpointRounding.AwayFromZero);
You can achieve that by using the Method of Math.Round() or decimal.Round()-:
Math.Round(amt)
Math.Round(amt, Int32) and other overloading methods.
decimal.Round(amt)
decimal.Round(amt, 2) and other overloding methods.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
c# - How do I round a decimal value to 2 decimal places (for output on a page)
how to return decimal with long rest after the point like that:
3.786444499963
to this:
3.787
its not just cut the points it also round the rest of the number
Math.Ceiling(3.786444499963 * 1000) / 1000;
But the generally accepted rounding of 3.786444499963 to three decimal places is 3.786. Why do you think otherwise?
Thus:
var round = Math.Round(3.786444499963m, 3, MidpointRounding.AwayFromZero);
Console.WriteLine(round == 3.786m); // prints true
If you want it to ALWAYS round up:
var round = Math.Round(3.786444499963m + 0.0005m, 3);
Console.WriteLine(round == 3.787m); // prints true
Do you see what I did there? I added 0.0005m to the input before using Math.Round. In general, to round x to n decimal places,
var round = Math.Round(x + 5m * Convert.ToDecimal(Math.Pow(10, -n - 1)), n);
Or, perhaps, to avoid the ugly double/decimal conversion:
int k = 1;
decimal value = 5m;
while(k <= n + 1) { value /= 10m; k++; }
var round = Math.Round(x + value, n);
There's an edge case you need to be aware of. What happens to 3.786? Should it be rounded up to 3.787 or remain at 3.786? You haven't specified what you want exactly, so I'll leave this edge case to you.
RoundUp(3.786444499963M, 3);
static decimal RoundUp(decimal dec, int precision)
{
decimal rounder = (decimal)(0.5 * Math.Pow(10, -precision));
return Math.Round(dec + rounder, precision);
}
I have a decimal number which can be like the following:
189.182
I want to round this up to 2 decimal places, so the output would be the following:
189.19
Is there built in functionality for this in the Math class, or something else? I know the ceiling function exists but this doesn't seem to do what I want - it'll round to the nearest int, so just '189' in this case.
Multiply by 100, call ceiling, divide by 100 does what I think you are asking for
public static double RoundUp(double input, int places)
{
double multiplier = Math.Pow(10, Convert.ToDouble(places));
return Math.Ceiling(input * multiplier) / multiplier;
}
Usage would look like:
RoundUp(189.182, 2);
This works by shifting the decimal point right 2 places (so it is to the right of the last 8) then performing the ceiling operation, then shifting the decimal point back to its original position.
You can use:
decimal n = 189.182M;
n = System.Math.Ceiling (n * 100) / 100;
An explanation of the various rounding functions can be found here.
Be aware that formulae like this are still constrained by the limited precision of the double type, should that be the type you are using (your question stated decimal but it's possible you may just have meant a floating point value with fractional component rather than that specific type).
For example:
double n = 283.79;
n = System.Math.Ceiling (n * 100);
will actually give you 28380, not the 283.79 you would expect(a).
If you want accuarate results across the board, you should definitely be using the decimal type.
(a) This is because the most accurate IEEE754 double precision representation of 283.79 is actually:
283.790000000000020463630789891
That extra (admittedly minuscule) fractional component beyond the .79 gets ceilinged up, meaning it will give you a value higher than you would expect.
var numberToBeRound1 = 4.125;
var numberToBeRound2 = 4.175;
var numberToBeRound3 = 4.631;
var numberToBeRound4 = 4.638;
var numberOfDecimalPlaces = 2;
var multiplier = Math.Pow(10, numberOfDecimalPlaces);
//To Round Up => 4.13
var roundedUpNumber = Math.Ceiling(numberToBeRound1 * multiplier) / multiplier;
//To Round Down => 4.12
var roundedDownNumber = Math.Floor(numberToBeRound1 * multiplier) / multiplier;
//To Round To Even => 4.12
var roundedDownToEvenNumber = Math.Round(numberToBeRound1, numberOfDecimalPlaces, MidpointRounding.ToEven);
//To Round To Even => 4.18
var roundedUpToEvenNumber = Math.Round(numberToBeRound2, numberOfDecimalPlaces, MidpointRounding.ToEven);
//To Round To Away From Zero => 4.63
var roundedDownToAwayFromZero = Math.Round(numberToBeRound3, numberOfDecimalPlaces, MidpointRounding.AwayFromZero);
//To Round To Away From Zero => 4.64
var roundedUpToAwayFromZero2 = Math.Round(numberToBeRound4, numberOfDecimalPlaces, MidpointRounding.AwayFromZero);
How about
0.01 * ceil(100 * 189.182)
In .NET Core 3.0 and later versions, three additional rounding strategies are available through the MidpointRounding enumeration.
Besides MidpointRounding.AwayFromZero and MidpointRounding.ToEven it now includes:
1. MidpointRounding.ToNegativeInfinity
2. MidpointRounding.ToPositiveInfinity
3. MidpointRounding.ToZero
For this specific question you need to use MidpointRounding.ToPositiveInfinity, this will round the number up always.
Note this only works if the number isn't negative. See table below for examples.
Original number
ToNegativeInfinity
ToPositiveInfinity
ToZero
3.55
3.5
3.6
3.5
2.83
2.8
2.9
2.8
2.54
2.5
2.6
2.5
2.16
2.1
2.2
2.1
-2.16
-2.2
-2.1
-2.1
-2.54
-2.6
-2.5
-2.5
-2.83
-2.9
-2.8
-2.8
-3.55
-3.6
-3.5
-3.5
For more information about midpointrounding see https://learn.microsoft.com/en-us/dotnet/api/system.midpointrounding
And of course the code to make it work:
// function explained: Math.Round(number, amount of decimals, MidpointRounding);
decimal number = 189.182m;
number = Math.Round(number, 2, MidpointRounding.ToPositiveInfinity);
// result: number = 189.19
public static decimal RoundUp(decimal input, int places)
{
decimal multiplier = (decimal)Math.Pow(10, places);
return decimal.Ceiling(input * multiplier) / multiplier;
}
// Double will return the wrong value for some cases. eg: 160.80
public static decimal RoundUp(decimal input, int places)
{
decimal multiplier = Convert.ToDecimal(Math.Pow(10, Convert.ToDouble(places)));
return Math.Ceiling(input * multiplier) / multiplier;
}
One other quirky but fun way to do it is Math.Round() after offsetting the number.
decimal RoundUp(decimal n, int decimals)
{
n += decimal.Parse($"1e-{decimals}", System.Globalization.NumberStyles.AllowExponent) / 2;
n -= 1e-28m;
return Math.Round(n, decimals);
}
decimal RoundDown(decimal n, int decimals)
{
n -= decimal.Parse($"1e-{decimals}", System.Globalization.NumberStyles.AllowExponent) / 2;
n += 1e-28m;
return Math.Round(n, decimals);
}
Is has the advantage of not using Math.Pow() which uses double and thus can cause unpredictable rounding errors.
This solution basically uses the fact that midpoint rounding can be turned into up/down rounding if you increase/decrease the number a little:
Math.Round(3.04m, 1) is 3.0 - not what we want
Let's add 0.04(9) to it
Math.Round(3.0899999999999999999999999999m, 1) is 3.1 - success!
Subtracting 1e-28m (= 0.0000000000000000000000000001) is important, because we want to be able to round up 3.0000000000000000000000000001 to 4, but 3.0000000000000000000000000000 should stay 3.