Can someone please provide code (any language will do, but I write the .Net languages and VB6) for an algorithm that rounds numbers ending with 5 towards a given number?
RoundTo(double value, double toWards, int numberOfDigitsBehindComma)
RoundTo(1.25,1,1)=1.2
RoundTo(1.25,2,1)=1.3
RoundTo(1.26,1,1)=1.3
RoundTo(1.24,2,1)=1.2
Include a solution for negative numbers please.
EDIT: There seems to be a lot of confusion about my requirements I will fill in all the Assertions that the resulting code has to meet. My solution does so.
[TestMethod]
public void RoundTowards()
{
double x=3.44;double y=3.45;double z=4.45;
double a = 3.51; double b = 4.5001; double c = -1.14; double d = -1.15;
var mean=4;
Assert.AreEqual(3.4,x.RoundTowards(mean,1));
Assert.AreEqual(3.5, y.RoundTowards(mean, 1));
Assert.AreEqual(4.4, z.RoundTowards(mean, 1));
Assert.AreEqual(3.5, a.RoundTowards(mean, 1));
Assert.AreEqual(4.5, b.RoundTowards(mean, 1));
mean = 5;
Assert.AreEqual(3.4, x.RoundTowards(mean, 1));
Assert.AreEqual(3.5, y.RoundTowards(mean, 1));
Assert.AreEqual(4.5, z.RoundTowards(mean, 1));
Assert.AreEqual(3.5, a.RoundTowards(mean, 1));
Assert.AreEqual(4.5, b.RoundTowards(mean, 1));
mean = 3;
Assert.AreEqual(3.4, x.RoundTowards(mean, 1));
Assert.AreEqual(3.4, y.RoundTowards(mean, 1));
Assert.AreEqual(4.4, z.RoundTowards(mean, 1));
Assert.AreEqual(3.5, a.RoundTowards(mean, 1));
Assert.AreEqual(4.5, b.RoundTowards(mean, 1));
Assert.AreEqual(Math.Round(-1.1,4),Math.Round( c.RoundTowards(mean, 1),4));
Assert.AreEqual(Math.Round(-1.1,4),Math.Round(d.RoundTowards(mean, 1),4));
mean = -2;
Assert.AreEqual(Math.Round(3.4,4),Math.Round( x.RoundTowards(mean, 1),4));
Assert.AreEqual(Math.Round(3.4,4),Math.Round( y.RoundTowards(mean, 1),4));
Assert.AreEqual(Math.Round(4.4,4),Math.Round( z.RoundTowards(mean, 1),4));
Assert.AreEqual(Math.Round(3.5,4),Math.Round( a.RoundTowards(mean, 1),4));
Assert.AreEqual(Math.Round(4.5,4),Math.Round( b.RoundTowards(mean, 1),4));
Assert.AreEqual(Math.Round(-1.1, 4), Math.Round(c.RoundTowards(mean, 1), 4));
Assert.AreEqual(Math.Round(-1.2, 4), Math.Round(d.RoundTowards(mean, 1), 4));
}
[TestMethod]
public void RoundTowardsTowardZero()
{
double x = 3.45; double y = -3.45;
double a = -3.551; double b = 4.551; double c = 4.5500001; double d = 4.5501;
var mean = 0;
Assert.AreEqual(3.4, x.RoundTowards(mean, 1));
Assert.AreEqual(-3.4, y.RoundTowards(mean, 1));
Assert.AreEqual(-3.6, a.RoundTowards(mean, 1));
Assert.AreEqual(4.6, b.RoundTowards(mean, 1));
Assert.AreEqual(4.5, c.RoundTowards(mean, 1));
Assert.AreEqual(4.6, d.RoundTowards(mean, 1));
}
[TestMethod]
public void Test14_55()
{
Assert.AreEqual((14.55).RoundTowards(9, 1) ,14.5);
Assert.AreEqual((14.55).RoundTowards(15,1), 14.6);
}
[TestMethod]
public void Test14_5499999()
{
Assert.AreEqual((14.54999999).RoundTowards(9, 1) ,14.5);
Assert.AreEqual((14.54999999).RoundTowards(15,1), 14.6);
}
Thanks!!!
I think all the solutions here are too complicated. Your problem seems to be that you want to be able to control the direction of rounding when you are exactly at the midpoint. You can reduce the problem of having N digits trailing the decimal point just by multiplying and then dividing by an integer power of 10, so it’s enough to fix this for the case where the “5” is right after to the decimal point. If you want to round number x so that e.g. 0.5 is rounded upwards to 1, you just do
If you want to round x so that 0.5 is rounded downwards to 0, you just do
These work because if x = 0.5, floor(x + 0.5) = floor(1) = 1, and ceil(x – 0.5) = ceil(0) = 0. To see that other numbers are rounded always correctly,
so the whole code becomes:
This solution also offloads the whole process to the actual mathematics library and your CPU’s ALU, and is therefore very robust. This handles obviously negative numbers without any extra tweaking, and works correctly with infinities etc.