C# midpointrounding down to zero - c#

I know about MidpointRounding.AwayFromZero and MidpointRounding.ToEven, but I think I want something inbetween. It is for a promotions module, so discounted prices must round down if the value is .5.
For example, I would like:
£1.244 to round to £1.24
£1.245 to round to £1.24
£1.246 to round to £1.25
As I understand it, .AwayFromZero would round the middle value to £1.25 and .ToEven would round correctly to £1.24, but £1.335 would be rounded to £1.34, rather than £1.33 which is what I want.
Does anyone know how to accomplish this?
Thanks, Jon

There is a lot of unspecified behavior. Let's keep it safe and do the rounding explicitly, ignoring negatives since this is about money:
public static decimal Promotion(decimal value) {
decimal unround = decimal.Floor(value * 100m);
decimal fraction = value * 100m - unround;
if (fraction <= 0.5m) return unround / 100m;
else return (unround + 1m) / 100m;
}

Math.ceiling(x - 0.5)
Should do the trick.

Ussually to do something like this you subtract .001 from your value, then round normally.
1.244 - .001 = 1.243 = 1.24
1.245 - .001 = 1.244 = 1.24
1.246 - .001 = 1.245 = 1.25
1.300 - .001 = 1.299 = 1.3
In this case, you REALLY want to put this in it's own function/extrension method, whatever, and document with a function WHY you subtract .001 before rounding.

Related

How to change a decimal value so it ends in a specified digit?

I have a decimal value stored in 'amount' and another decimal value called 'roundTo'.
I'm trying to take whatever 'amount' is, round it to whatever 'roundTo' is set to and then set the final value in newAmount, but it should round to the closest value to roundTo.
Ex.
amount = 2.01
roundTo = 0.09
newAmount becomes 1.99
Ex.
amount = 2.07
roundTo = 0.09
newAmount becomes 2.09
I'm trying to get it to work with all possible values, so roundTo can be anything from 0.01 to 0.09
I've tried doing this like
newAmount = (Math.Round(amount * 10m) / 10m - 0.01m);
The above only really works for when roundTo is 0.09 (using a switch case where if roundTo was 0.09, the above would run).
I also tried
newAmount = Math.Round(amount / roundTo, MidpointRounding.AwayFromZero) * roundTo;
But didn't get any good data from this.
Can anyone point me in the right direction? Thanks!!
decimal amount = 2.06m;
decimal roundTo = 0.04m;
decimal newAmount = Math.Round(amount - roundTo, 1) + roundTo;

how to leave decimal places to 1 without rounding

I need to convert my value 2.8634 to 2.8. I tried the following ,
var no = Math.Round(2.8634,2,MidpointRounding.AwayFromZero)
I'm getting 2.87.
Suggest me some ideas how to convert.
Thanks
This might do the trick for you
decimal dsd = 2.8634m;
var no = Math.Truncate(dsd * 10) / 10;
Math.Truncate calculates the integral part of a specified decimal number. The number is rounded to the nearest integer towards zero.
You can also have a look on the difference between Math.Floor, Math.Ceiling, Math.Truncate, Math.Round with an amazing explanation.
Use this one.Hope this will work for you.
var no = Math.Round(2.8634,1,MidpointRounding.AwayFromZero)
It's a tad more cryptic (but more efficient) than calling a Math method, but you can simply multiply the value by 10, cast to an integer (which effectively truncates the decimal portion), and then divide by 10.0 (or 10d/10f, all just to ensure we don't get integer division) to get back the value you are after. I.e.:
float val = 2.8634;
val = ((int)(val * 10)) / 10.0;

Unexpected decimal value behavior

I used to think I understand the difference between decimal and double values, but now I'm not able to justify the behavior of this code snippet.
I need to divide the difference between two decimal numbers in some intervals, for example:
decimal minimum = 0.158;
decimal maximum = 64.0;
decimal delta = (maximum - minimum) / 6; // 10.640333333333333333333333333
Then I create the intervals in reverse order, but the first result is already unexpected:
for (int i = 5; i >= 0; i--)
{
Interval interval = new Interval(minimum + (delta * i), minimum + (delta * (i + 1));
}
{53.359666666666666666666666665, 63.999999999999999999999999998}
I would expect the maximum value to be exactly 64. What am I missing here?
Thank you very much!
EDIT: if I use double instead of decimal it seems to works properly!
You're not missing anything. This is the result of rounding the numbers multiple times internally, i.e. compounding loss of precision. The delta, to begin with, isn't exactly 10.640333333333333333333333333, but the 3s keep repeating endlessly, resulting in a loss of precision when you multiply or divide using this decimal.
Maybe you could do it like this instead:
for (decimal i = maximum; i >= delta; i -= delta)
{
Interval interval = new Interval(i - delta, i);
}
Double has 16 digits precision while Decimal has 29 digits precision. Thus, double is more than likely would round it off than decimal.

What is the fastest way to round the digit after a decimal (double)?

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];

How do you round a number to two decimal places in C#?

I want to do this using the Math.Round function
Here's some examples:
decimal a = 1.994444M;
Math.Round(a, 2); //returns 1.99
decimal b = 1.995555M;
Math.Round(b, 2); //returns 2.00
You might also want to look at bankers rounding / round-to-even with the following overload:
Math.Round(a, 2, MidpointRounding.ToEven);
There's more information on it here.
Try this:
twoDec = Math.Round(val, 2)
If you'd like a string
> (1.7289).ToString("#.##")
"1.73"
Or a decimal
> Math.Round((Decimal)x, 2)
1.73m
But remember! Rounding is not distributive, ie. round(x*y) != round(x) * round(y). So don't do any rounding until the very end of a calculation, else you'll lose accuracy.
Personally I never round anything. Keep it as resolute as possible, since rounding is a bit of a red herring in CS anyway. But you do want to format data for your users, and to that end, I find that string.Format("{0:0.00}", number) is a good approach.
Wikipedia has a nice page on rounding in general.
All .NET (managed) languages can use any of the common language run time's (the CLR) rounding mechanisms. For example, the Math.Round() (as mentioned above) method allows the developer to specify the type of rounding (Round-to-even or Away-from-zero). The Convert.ToInt32() method and its variations use round-to-even. The Ceiling() and Floor() methods are related.
You can round with custom numeric formatting as well.
Note that Decimal.Round() uses a different method than Math.Round();
Here is a useful post on the banker's rounding algorithm.
See one of Raymond's humorous posts here about rounding...
// convert upto two decimal places
String.Format("{0:0.00}", 140.6767554); // "140.67"
String.Format("{0:0.00}", 140.1); // "140.10"
String.Format("{0:0.00}", 140); // "140.00"
Double d = 140.6767554;
Double dc = Math.Round((Double)d, 2); // 140.67
decimal d = 140.6767554M;
decimal dc = Math.Round(d, 2); // 140.67
=========
// just two decimal places
String.Format("{0:0.##}", 123.4567); // "123.46"
String.Format("{0:0.##}", 123.4); // "123.4"
String.Format("{0:0.##}", 123.0); // "123"
can also combine "0" with "#".
String.Format("{0:0.0#}", 123.4567) // "123.46"
String.Format("{0:0.0#}", 123.4) // "123.4"
String.Format("{0:0.0#}", 123.0) // "123.0"
If you want to round a number, you can obtain different results depending on: how you use the Math.Round() function (if for a round-up or round-down), you're working with doubles and/or floats numbers, and you apply the midpoint rounding. Especially, when using with operations inside of it or the variable to round comes from an operation. Let's say, you want to multiply these two numbers: 0.75 * 0.95 = 0.7125. Right? Not in C#
Let's see what happens if you want to round to the 3rd decimal:
double result = 0.75d * 0.95d; // result = 0.71249999999999991
double result = 0.75f * 0.95f; // result = 0.71249997615814209
result = Math.Round(result, 3, MidpointRounding.ToEven); // result = 0.712. Ok
result = Math.Round(result, 3, MidpointRounding.AwayFromZero); // result = 0.712. Should be 0.713
As you see, the first Round() is correct if you want to round down the midpoint. But the second Round() it's wrong if you want to round up.
This applies to negative numbers:
double result = -0.75 * 0.95; //result = -0.71249999999999991
result = Math.Round(result, 3, MidpointRounding.ToEven); // result = -0.712. Ok
result = Math.Round(result, 3, MidpointRounding.AwayFromZero); // result = -0.712. Should be -0.713
So, IMHO, you should create your own wrap function for Math.Round() that fit your requirements. I created a function in which, the parameter 'roundUp=true' means to round to next greater number. That is: 0.7125 rounds to 0.713 and -0.7125 rounds to -0.712 (because -0.712 > -0.713). This is the function I created and works for any number of decimals:
double Redondea(double value, int precision, bool roundUp = true)
{
if ((decimal)value == 0.0m)
return 0.0;
double corrector = 1 / Math.Pow(10, precision + 2);
if ((decimal)value < 0.0m)
{
if (roundUp)
return Math.Round(value, precision, MidpointRounding.ToEven);
else
return Math.Round(value - corrector, precision, MidpointRounding.AwayFromZero);
}
else
{
if (roundUp)
return Math.Round(value + corrector, precision, MidpointRounding.AwayFromZero);
else
return Math.Round(value, precision, MidpointRounding.ToEven);
}
}
The variable 'corrector' is for fixing the inaccuracy of operating with floating or double numbers.
This is for rounding to 2 decimal places in C#:
label8.Text = valor_cuota .ToString("N2") ;
In VB.NET:
Imports System.Math
round(label8.text,2)
I know its an old question but please note for the following differences between Math round and String format round:
decimal d1 = (decimal)1.125;
Math.Round(d1, 2).Dump(); // returns 1.12
d1.ToString("#.##").Dump(); // returns "1.13"
decimal d2 = (decimal)1.1251;
Math.Round(d2, 2).Dump(); // returns 1.13
d2.ToString("#.##").Dump(); // returns "1.13"
Had a weird situation where I had a decimal variable, when serializing 55.50 it always sets default value mathematically as 55.5. But whereas, our client system is seriously expecting 55.50 for some reason and they definitely expected decimal. Thats when I had write the below helper, which always converts any decimal value padded to 2 digits with zeros instead of sending a string.
public static class DecimalExtensions
{
public static decimal WithTwoDecimalPoints(this decimal val)
{
return decimal.Parse(val.ToString("0.00"));
}
}
Usage should be
var sampleDecimalValueV1 = 2.5m;
Console.WriteLine(sampleDecimalValueV1.WithTwoDecimalPoints());
decimal sampleDecimalValueV1 = 2;
Console.WriteLine(sampleDecimalValueV1.WithTwoDecimalPoints());
Output:
2.50
2.00
One thing you may want to check is the Rounding Mechanism of Math.Round:
http://msdn.microsoft.com/en-us/library/system.midpointrounding.aspx
Other than that, I recommend the Math.Round(inputNumer, numberOfPlaces) approach over the *100/100 one because it's cleaner.
You should be able to specify the number of digits you want to round to using Math.Round(YourNumber, 2)
You can read more here.
Math.Floor(123456.646 * 100) / 100
Would return 123456.64
string a = "10.65678";
decimal d = Math.Round(Convert.ToDouble(a.ToString()),2)
public double RoundDown(double number, int decimalPlaces)
{
return Math.Floor(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}

Categories

Resources