C# decimal number round after point rest [duplicate] - c#

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);
}

Related

Why is x 1 when assigning a double?

I'm very new with C#.
I don't understand why is x = 1 and not 1.4.
Can please somebody explain me this?
double x = (double)(12 / 5 - 3 % 2);
Console.WriteLine(x);
Because this is NOT about double.
You are integer-executing
(12 / 5 - 3 % 2);
and THEN casting to double. If you want this to be about double, then make sure at least one of the numbers is a double. In your case just mark the literals as double.
(12d / 5d - 3d % 2d);
is all doubles. As long as one is a double, the operation happens as double - but your original case makes all the calculations, THEN casts to double. So they happen as integer.
You're doing integer math and then converting to double. 12 / 5 = 2, 3 % 2 = 1, and 2 - 1 = 1.
Welcome to stackoverflow! :)
The problem is that you are operating all int, and afterwards converting them to double.
You need to make sure that you are operating with doubles from the beginning.
Try out the code in here: https://dotnetfiddle.net/xaQjKL
using System;
public class Program
{
public static void Main()
{
// Doubles from the beggining
double d_twelve = 12.0;
double d_five = 5.0;
double x = (double)(d_twelve / d_five);
Console.WriteLine($"Using all doubles: {x}");
// First split two int, then convert the result to double
int i_twelve = 12;
int i_five = 5;
x = (double)(i_twelve / i_five);
Console.WriteLine($"Using ints, and converting at the end to double: {x}");
// And now your code:
x = (double)(12 / 5 - 3 % 2);
Console.WriteLine($"Your original code: {x}");
// And now your code fixed (notice the 12 => 12.0):
x = (double)(12.0 / 5 - 3 % 2);
Console.WriteLine($"Changing 12 by 12.0: {x}");
}
}
You are doing operations with integers and then casting he result to a double.
double x = (12d / 5d - 3d % 2d);
Console.WriteLine(x);
Adding d after a number will make it a double while adding f will make it a float.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types#real-literals
Because you use integer values inside the parenthesis, and the expression is calculated using integer math before being cast to double.
You can use a double value for the first value and it should be enough:
> double x = (12d / 5) - (3 % 2);
> Console.WriteLine(x);
1.4

Why am I getting 0.0 with this code? [duplicate]

This question already has answers here:
Why I cannot the get percentage by using Int
(9 answers)
Closed 6 years ago.
When I enter, in the Windows Calculator utility, "15036/18218*100=" it returns 82.53375782193435
What I really want is 17.47 (100 - 82.53), but that's beside the point at the moment.
With this code:
// Example: thisQty == 3182; totalQty == 18218
private string GetPercentage(int thisQty, int totalQty)
{
int diff = totalQty - thisQty; // this equates to 15036
double prcntg = (diff/totalQty)*100; // this equates to 0.0 for some reason
return string.Format("{0}%", prcntg);
}
...I'm getting 0.0 for the prcntg value. Why? ISTM that this is the same operation that I'm doing by hand in the Calculator utility. Why doesn't it return 82.53375782193435?
The dividing of 2 ints will be an int even if the correct mathematical answer is with a fraction.
In order to have it keep the decimal part you must divide with a number of a type that holds the fraction part (like double or decimal):
Console.WriteLine(GetPercentage(3182, 18218));
private string GetPercentage(int thisQty, int totalQty)
{
int diff = totalQty - thisQty; // this equates to 15036
double prcntg = (diff / (double)totalQty) * 100;
return string.Format("{0}%", prcntg);
}
BTW - it doesn't matter if you cast to double the diff or the totalQty - for both it will do the / operation returning a double - which means keeping the fraction part
You are using an integer value, (which doesn't store factional part), so cast it to double, or use the parameter type as double (my recommendation). Your operation, 15036/18218 resolves to, 0.82 and in an integer value that is stored as 0... Where finally 0 * 100 is going to resolve to 0 anyways and that is where you get the result.
Try this instead,
private string GetPercentage(double thisQty, double totalQty)
{
double diff = totalQty - thisQty; // this equates to 15036
double prcntg = (diff/totalQty) * 100.0; // this equates to 0.0 for some reason
return string.Format("{0}%", prcntg);
}
This would have the fractional part too and you will get the result.
Based on Gilad Green's answer, here is what I ended up with, which gives the value I ultimately want, and also rounds the value to an integer:
private string GetPercentage(int thisQty, int totalQty)
{
int diff = totalQty - thisQty;
double prcntg = (diff / (double)totalQty) * 100;
prcntg = 100 - prcntg;
int roundedPercent = Convert.ToInt32(prcntg);
return string.Format("{0}%", roundedPercent);
}

Truncating decimal number to one decimal digit

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.

How to round up or down in C#?

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.

Rounding up to 2 decimal places in C#

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.

Categories