Reputation: 87
C# - truncate decimals beyond first positive
a number is 0.009012
result should be 0.009
or is 1.1234
and 'd be 1.1
or 2.099
~ 2.09
and so on
in a fast and optimum way
Upvotes: 1
Views: 168
Reputation: 14059
Try this method:
private static string RoundSpecial(double x)
{
string s = x.ToString();
int dotPos = s.IndexOf('.');
if (dotPos != -1)
{
int notZeroPos = s.IndexOfAny(new[] { '1', '2', '3', '4', '5', '6', '7', '8', '9' }, dotPos + 1);
return notZeroPos == -1 ? s : s.Substring(0, notZeroPos + 1);
}
return s;
}
I'm not sure that it is the fastest and optimal method, but it does what you want.
Second approach is to use Log10
and %
:
private static double RoundSpecial(double x)
{
int pos = -(int)Math.Log10(x - (int)x);
return Math.Round(x - (x % Math.Pow(0.1, pos + 1)), pos + 1);
}
Upvotes: 2
Reputation: 5566
Think mathematically, use logarithmus with base 10
this function will just take the first cipher
public double RoundOnFirstDecimal(double number)
{
int shift = -1 * ((int)Math.Floor(Math.Log10(number)));
return Math.Floor(number * Math.Pow(10, shift)) / Math.Pow(10, shift);
}
But you want to have it this way: (will shift only regarding the decimal fractions, but not full numbers)
public double RoundOnFirstDecimal(double number)
{
int shift = -1 * ((int)Math.Floor(Math.Log10(number % 1)));
return Math.Floor(number % 1 * Math.Pow(10, shift)) / Math.Pow(10, shift) + number - number % 1;
}
thats gonna be significantly faster than any regex or looping
Upvotes: 3
Reputation: 444
if you don't want to use the Math
library:
static double truncateMyWay(double x)
{
double afterDecimalPoint = x - (int)x;
if (afterDecimalPoint == 0.0) return x;
else
{
int i = 0;
int count10 = 1;
do
{
afterDecimalPoint *= 10;
count10 *= 10;
i++;
} while ((int) afterDecimalPoint == 0);
return ((int)(x * count10))/((double)count10);
}
}
Happy Codding! ;-)
Upvotes: 0
Reputation: 17964
Here's a solution that uses math instead of string logic:
double nr = 0.009012;
var partAfterDecimal = nr - (int) nr;
var partBeforeDecimal = (int) nr;
int count = 1;
partAfterDecimal*=10;
int number = (int)(partAfterDecimal);
while(number == 0)
{
partAfterDecimal *= 10;
number = (int)(partAfterDecimal);
count++;
}
double dNumber = number;
while(count > 0){
dNumber /= 10.0;
count--;
}
double result = (double)partBeforeDecimal + dNumber;
result.Dump();
Upvotes: 0
Reputation: 3752
You may try regular expression too:
decimal d = 2.0012m;
Regex pattern = new Regex(@"^(?<num>(0*[1-9]))\d*$");
Match match = pattern.Match(d.ToString().Split('.')[1]);
string afterDecimal = match.Groups["num"].Value; //afterDecimal = 001
Upvotes: 0