How to round to any number in C#? - c#

I am in the middle of making a calculator in C# and I want to round to nearest 1, 10, 100, etc and also like nearsest 0.1, 0.001, etc. I have seen other projects that tell me how to do it but I tried and they don't seem to work.
I've tried:
textBox1.Text = Convert.ToString(Math.Round(Convert.ToDouble(Label1.Text), Convert.ToInt32(textBox1.Text), MidpointRounding.AwayFromZero));
and...
textBox1.Text = Convert.ToString(Math.Round(Convert.ToDouble(Label1.Text), Convert.ToInt32(textBox1.Text)));
and...
textBox1.Text = Convert.ToString(Convert.ToInt32(Label1.Text) / Convert.ToInt32(textBox1.Text) * Convert.ToInt32(textBox1.Text));

Math.Round has overloads that allow you to round to a particular decimal.
e.g.
Math.Round(0.05, 1, MidpointRounding.AwayFromZero);
will result in 0.1
If you want to round to the nearest 10, 100, etc, you will need to do a bit more math.
Math.Round((double)50 / 100, MidpointRounding.AwayFromZero) * 100;
results in 100, for rounding to the nearest hundred, while
Math.Round((double)55 / 10, MidpointRounding.AwayFromZero) * 10;
will get you to the nearest 10, in this case 60.

You can make an Extension method to do it, using the same idea from Jonathon's answer. You divide the input by the interval you choose, round it using Math.Round, and then multiply the rounded number by the interval.
static class Extensions
{
public static int RoundToInterval(this int i, int interval)
{
if (interval == 0)
{
throw new ArgumentException("The specified interval cannot be 0.", nameof(interval));
}
return ((int)Math.Round((double)i / (double)interval)) * interval;
}
}
Calling it will look like so.
int input = 13;
var result = input.RoundToInterval(10);
The result of the previous example call will be 10. Change input to 16, and the result will be 20. If you pass 100 as the argument to RoundToInterval, the result will be 0, and 51 (and 50 with the default MidpointRounding choice) will give the result of 100.

Related

Round to 25, 50, 75, 100

I'm not a Math person so I'm having a hard time to come up with a calculation to round the decimals to 25, 50, 75 and 100. And this will not be the typical round off because the decimals will not be decreased but only increased.
Example:
if 11.12, round to 11.25
if 11.34, round to 11.50
if 11.52, round to 11.75
if 11.76, round to 12.00
Here's my starting method:
public float RoundNearestCents(String price)
{
float srp;
return srp;
}
public float RoundNearestCents(double d)
{
return (double)(Math.Ceiling(d * 4)) / 4;
}
I suggest using types without floating point.
decimal RoundNearestCents(decimal price) {
// no problems with floating point as all calculations are exact
return Math.Floor((price * 100 + 24) / 25) * 25 / 100;
}
-- Why is your price string?
-- Because it's coming from a textbox.
I assume your textbox should support limiting your input to decimal numbers with at most 2 decimal places. So its value will be decimal already. However I don't know what is your application type. If you still want to accept string then consider using decimal.TryParse method to convert it to decimal.
My code may not be the best out there, but it will work.
In your function create a float and an int like so.
public float RoundNearestCents(String price)
{
float srp = float.Parse(price);
int srp1 = Int32.Parse(price);
if((srp-srp1)>=0.5)
srp1++;
else
return srp1;
return srp1;
}
The int would truncate out the decimal part, which is like flooring the price.
I would use something like this:
float RoundNearestCents(float price)
{
price*=(100/25.0); // now fractions are going away
if (price-floor(price)>=0.5) price++; // round up if fraction above 0.5
return floor(price)*(25.0/100.0); // cut of the fraction and restore original range
}
This is one way:
public decimal RoundNearestCents(decimal price)
{
decimal srp = price * 100;
decimal m = srp % 25;
srp = srp - m + (m > 0 ? 25 : 0);
return srp / 100;
}

Incorrect linear interpolation with large x values using Math.Net Numerics

I'm trying to use Math.NET Numerics to do interpolation of a DateTime - Value series. I started off with linear interpolation, but am getting some very off looking results.
Running this test:
public class script{
public void check_numerics()
{
var ticks = DateTime.Now.Ticks;
Console.WriteLine("Ticks: " + ticks);
var xValues = new double[] { ticks, ticks + 1000, ticks + 2000, ticks + 3000, ticks + 4000, ticks + 5000 };
var yValues = new double[] {0, 1, 2, 3, 4, 5};
var spline = Interpolate.LinearBetweenPoints(xValues, yValues);
var ticks2 = ticks;
for (int i = 0; i < 10; i++)
{
ticks2 += 500;
Console.WriteLine(spline.Interpolate(ticks2));
}
}
}
This gives:
Ticks: 635385235576843379
0.5
1
1.5
2
2.42857142857143 // this should be 2.5
3
3.5
4
4.5
5
Notice that 2.4285 is fairly wrong. At a different time (different ticks value) a different value will be "wrong". Is there a "bug" with large x values in Math.NET or am I expecting too much?
Just confirming the comments above as the maintainer of Math.NET Numerics:
The distance (epsilon) between the closest numbers of this magnitude that can be represented at double precision is 128:
Precision.EpsilonOf(ticks); // 128
This means that if you add or substract 128/2-1 = 63 from this number, you get back exactly the same number:
long ticks = DateTime.Now.Ticks // 635385606515570758
((long)(double)ticks) // 635385606515570816
((long)(63+(double)ticks)) // 635385606515570816
((long)(-63+(double)ticks)) // 635385606515570816
((long)(65+(double)ticks)) // 635385606515570944
((long)(-65+(double)ticks)) // 635385606515570688
The incremental steps of 500 are very close to these 128 and effectively get rounded to multiples of 128 (e.g. 512), so it's not surprising that there will be some artifacts like this.
If you reduce the time precision to milliseconds by dividing the ticks by 10000, as suggested by James, you get an epsilon of 0.0078125, and accurate results even for steps of 1 instead of 500.
Precision.EpsilonOf(ticks/10000); // 0.0078125

Keep rounding upto specified digit if non zero

I want to round Up decimal values upto two points. But for any number which is less than 0.01, I want to return 0.01.
RoundUp(0.146,2) should return 0.15
RoundUp(0.0003,2) should return 0.01
In C#, I am currently using Math.Round, with MidpointRounding.AwayFromZero parameter, but for
Math.Round(0.0003, 2, MidpointRounding.AwayFromZero);
it returns 0.
Is there any in built method in Math namespace, which I can use to get desired behavior?
Currently I am using this method
private double GetRoundUpValue(double price, int roundUpto)
{
Debug.Assert(roundUpto == 2 || roundUpto == 3);
var val = Math.Round(price, roundUpto, MidpointRounding.AwayFromZero);
Double minValue = roundUpto == 2 ? 0.01 : 0.001;
return val < minValue ? minValue : val;
}
But for any number which is less than 0.01, I want to return 0.01.
Then why not keep it simple and just use something like this:
Math.Max(Math.Round(0.0003, 2, MidpointRounding.AwayFromZero), 0.01);
Or if you need something more general, to round to n decimal places, use something like this:
private double GetRoundUpValue(double price, int places)
{
var minValue = Math.Pow(0.1, places);
return Math.Max(Math.Round(price, places, MidpointRounding.AwayFromZero), minValue);
}
Also note, that 'rounding away from zero' is not the same as 'rounding up' (for that, you can look at Math.Ceiling). So I'd recommend either changing the name of this method or it's body to be more clear about what's actually going on inside of it.
For example:
private double GetRoundUpValue(double price, int places)
{
var scale = Math.Pow(10, places);
return Math.Ceiling(price * scale) / scale;
}

Get an enumerable range for a given min and max with a given number of steps

I am familiar with the Enumerable.Range method for generating an enumeration of values. But I would like something slightly different. I want to provide a min value, max value, and a number of desired points.
IE:
Method(double min, double max, int numberOfSteps)
taking
Method(0, 1000, 11);
would return
0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000
I figure for something like this, there must be a built-in method but my search hasn't turned anything up. Am I missing something?
Other than the fact that you want the values to be double, everything else can be done with Enumerable.Range. I don't think there's anything built-in to do what you want, but it's trivial to implement on top of Enumerable.Range:
return Enumerable.Range(0, steps)
.Select(i => min + (max - min) * ((double)i / (steps - 1)));
I've written that somewhat carefully so that you always end up with the final value. It does bork if you say you only want a single step though... you might want to guard against that and use Enumerable.Repeat(min, 1) in that case.
Just calculate 'Common Difference' & generate the series:
d = (max - min)/(numberOfSteps - 1)
Now, You can easily generate your series:
int [] a = new [numberOfSteps];
for(i=0; i<numberOfSteps ; i++)
{
a[i] = min + (numberOfSteps - 1)d;
}

How to Round to the nearest whole number in C#

How can I round values to nearest integer?
For example:
1.1 => 1
1.5 => 2
1.9 => 2
"Math.Ceiling()" is not helping me. Any ideas?
See the official documentation for more. For example:
Basically you give the Math.Round method three parameters.
The value you want to round.
The number of decimals you want to keep after the value.
An optional parameter you can invoke to use AwayFromZero rounding. (ignored unless rounding is ambiguous, e.g. 1.5)
Sample code:
var roundedA = Math.Round(1.1, 0); // Output: 1
var roundedB = Math.Round(1.5, 0, MidpointRounding.AwayFromZero); // Output: 2
var roundedC = Math.Round(1.9, 0); // Output: 2
var roundedD = Math.Round(2.5, 0); // Output: 2
var roundedE = Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // Output: 3
var roundedF = Math.Round(3.49, 0, MidpointRounding.AwayFromZero); // Output: 3
Live Demo
You need MidpointRounding.AwayFromZero if you want a .5 value to be rounded up. Unfortunately this isn't the default behavior for Math.Round(). If using MidpointRounding.ToEven (the default) the value is rounded to the nearest even number (1.5 is rounded to 2, but 2.5 is also rounded to 2).
Math.Ceiling
always rounds up (towards the ceiling)
Math.Floor
always rounds down (towards to floor)
what you are after is simply
Math.Round
which rounds as per this post
You need Math.Round, not Math.Ceiling. Ceiling always "rounds" up, while Round rounds up or down depending on the value after the decimal point.
there's this manual, and kinda cute way too:
double d1 = 1.1;
double d2 = 1.5;
double d3 = 1.9;
int i1 = (int)(d1 + 0.5);
int i2 = (int)(d2 + 0.5);
int i3 = (int)(d3 + 0.5);
simply add 0.5 to any number, and cast it to int (or floor it) and it will be mathematically correctly rounded :D
You can use Math.Round as others have suggested (recommended), or you could add 0.5 and cast to an int (which will drop the decimal part).
double value = 1.1;
int roundedValue = (int)(value + 0.5); // equals 1
double value2 = 1.5;
int roundedValue2 = (int)(value2 + 0.5); // equals 2
Just a reminder. Beware for double.
Math.Round(0.3 / 0.2 ) result in 1, because in double 0.3 / 0.2 = 1.49999999
Math.Round( 1.5 ) = 2
You have the Math.Round function that does exactly what you want.
Math.Round(1.1) results with 1
Math.Round(1.8) will result with 2.... and so one.
this will round up to the nearest 5 or not change if it already is divisible by 5
public static double R(double x)
{
// markup to nearest 5
return (((int)(x / 5)) * 5) + ((x % 5) > 0 ? 5 : 0);
}
I was looking for this, but my example was to take a number, such as 4.2769 and drop it in a span as just 4.3. Not exactly the same, but if this helps:
Model.Statistics.AverageReview <= it's just a double from the model
Then:
#Model.Statistics.AverageReview.ToString("n1") <=gives me 4.3
#Model.Statistics.AverageReview.ToString("n2") <=gives me 4.28
etc...
Using Math.Round(number) rounds to the nearest whole number.
Use Math.Round:
double roundedValue = Math.Round(value, 0)
var roundedVal = Math.Round(2.5, 0);
It will give result:
var roundedVal = 3
If your working with integers rather than floating point numbers, here is the way.
#define ROUNDED_FRACTION(numr,denr) ((numr/denr)+(((numr%denr)<(denr/2))?0:1))
Here both "numr" and "denr" are unsigned integers.
Write your own round method. Something like,
function round(x)
rx = Math.ceil(x)
if (rx - x <= .000001)
return int(rx)
else
return int(x)
end
decimal RoundTotal = Total - (int)Total;
if ((double)RoundTotal <= .50)
Total = (int)Total;
else
Total = (int)Total + 1;
lblTotal.Text = Total.ToString();

Categories

Resources