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;
}
Related
I have an interesting problem, I need to convert an int to a decimal.
So for example given:
int number = 2423;
decimal convertedNumber = Int2Dec(number,2);
// decimal should equal 24.23
decimal convertedNumber2 = Int2Dec(number,3);
// decimal should equal 2.423
I have played around, and this function works, I just hate that I have to create a string and convert it to a decimal, it doesn't seem very efficient:
decimal IntToDecConverter(int number, int precision)
{
decimal percisionNumber = Convert.ToDecimal("1".PadRight(precision+1,'0'));
return Convert.ToDecimal(number / percisionNumber);
}
Since you are trying to make the number smaller couldn't you just divide by 10 (1 decimal place), 100 (2 decimal places), 1000 (3 decimal places), etc.
Notice the pattern yet? As we increase the digits to the right of the decimal place we also increase the initial value being divided (10 for 1 digit after the decimal place, 100 for 2 digits after the decimal place, etc.) by ten times that.
So the pattern signifies we are dealing with a power of 10 (Math.Pow(10, x)).
Given an input (number of decimal places) make the conversion based on that.
Example:
int x = 1956;
int powBy=3;
decimal d = x/(decimal)Math.Pow(10.00, powBy);
//from 1956 to 1.956 based on powBy
With that being said, wrap it into a function:
decimal IntToDec(int x, int powBy)
{
return x/(decimal)Math.Pow(10.00, powBy);
}
Call it like so:
decimal d = IntToDec(1956, 3);
Going the opposite direction
You could also do the opposite if someone stated they wanted to take a decimal like 19.56 and convert it to an int. You'd still use the Pow mechanism but instead of dividing you would multiply.
double d=19.56;
int powBy=2;
double n = d*Math.Pow(10, powBy);
You can try create decimal explictly with the constructor which has been specially designed for this:
public static decimal IntToDecConverter(int number, int precision) {
return new decimal(Math.Abs(number), 0, 0, number < 0, (byte)precision);
}
E.g.
Console.WriteLine(IntToDecConverter(2423, 2));
Console.WriteLine(IntToDecConverter(1956, 3));
Outcome:
24.23
1.956
Moving the decimal point like that is just a function of multiplying/dividing by a power of 10.
So this function would work:
decimal IntToDecConverter(int number, int precision)
{
// -1 flips the number so its a fraction; same as dividing below
decimal factor = (decimal)Math.Pow(10, -1*precision)
return number * factor;
}
number/percisionNumber will give you an integer which you then convert to decimal.
Try...
return Convert.ToDecimal(number) / percisionNumber;
Convert your method like as below
public static decimal IntToDecConverter(int number, int precision)
{
return = number / ((decimal)(Math.Pow(10, precision)));
}
Check the live fiddle here.
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;
}
public class ExperienceTable
{
public static int MaxExperiencePoints;
public static double PercentToNextLevel;
public static void checkLevel(Hero player)
{
if (player.ExperiencePoints >= 0)
{
player.Level = 1;
MaxExperiencePoints = 15;
PercentToNextLevel = player.ExperiencePoints / MaxExperiencePoints;
}
}
Then drawing it to the screen using:
GameRef.SpriteBatch.DrawString(GUIFont, "" + ExperienceTable.PercentToNextLevel, new Vector2((int)player.Camera.Position.X + 1200, (int)player.Camera.Position.Y + 676), Color.White);
How come decimal places don't show up? Seems like the numbers are being rounded.
By default, the decimal place will not be shown if the double is already a rounded number in the first place. I'm guessing player.ExperiencePoints is an int. And int divided by another int will always result to an int, resulting in a rounded value.
Assuming that player.ExperiencePoints is really an int, and you want to have the fraction when dividing it, you should change the division line to the following:
PercentToNextLevel = (double) player.ExperiencePoints / MaxExperiencePoints;
And if you want to have the decimal places displayed eventhough it's .00, then change the ExperienceTable.PercentToNextLevel to something like the following.
ExperienceTable.PercentToNextLevel.ToString("0.00")
.ToString("0.00") will convert the double value to a string with 2 decimal places, and will round it to two decimal places if it have to.
I think
PercentToNextLevel = player.ExperiencePoints / MaxExperiencePoints;
is an integer division (that's if player.ExperiencePoints is an integer).
Try that:
PercentToNextLevel = (double)player.ExperiencePoints / MaxExperiencePoints;
If player.ExperiencePoints is also an int, then you are dividing an integer by an integer, and the result is a rounded integer. Instead, use
PercentToNextLevel = (double)player.ExperiencePoints / MaxExperiencePoints
I have a double typed variable. This variable stores information that is part of a more complex formula. Importantly, this variable can only include information up to the tenths location, or one decimal position (i.e. 10.1, 100.2, etc). However, when determining this value, it must be calculated such that anything past the tenths location is truncated, not rounded. For instance:
if the value equals 10.44, The variable value should be 10.4.
if the value equals 10.45, The variable value should also be set to 10.4
How do I truncate values in C# with respect to a decimal place?
Using an extension method:
public static double RoundDown(this double value, int digits)
{
int factor = Math.Pow(10,digits);
return Math.Truncate(value * factor) / factor;
}
Then you simply use it like this:
double rounded = number.RoundDown(2);
You have to do that by your own:
public static decimal Truncate(decimal value, int decimals)
{
if ((decimals < 0) || (decimals > 28))
{
throw new ArgumentOutOfRangeException("decimals", "The number of fractional decimals must be between 0 and 28.");
}
decimal integral = Math.Truncate(value);
decimal fractional = value - integral;
decimal shift = (decimal)Math.Pow(10, decimals);
fractional = Math.Truncate(shift * fractional);
fractional = fractional / shift;
return (integral + fractional);
}
System.Math.Truncate (d * 10) / 10
Generally, if you're working with numbers where the precise decimal representation is important, you should use decimal - not double.
With decimal, you can do something like...
decimal d = ...;
d = decimal.Truncate(d*10)/10;
If you use a double value, your truncated number will not generally be precisely representable - you may end up with excess digits or minor rounding errors. For example Math.Truncate((4.1-4.0)*10) is not 1, but 0.
While I would probably use Phillippe's answer, if you wanted to avoid scaling the number up (unlikely to be a problem for 1dp), you could:
public static double RoundDown(this double x, int numPlaces)
{
double output = Math.Round(x, numPlaces, MidpointRounding.AwayFromZero);
return (output > x ? output - Math.Pow(10, -numPlaces) : output);
}
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];