G.M.
G.M.

Reputation: 87

Truncate decimals beyond first positive

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

Answers (5)

Dmitry
Dmitry

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

fixagon
fixagon

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

Shamim
Shamim

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

Carra
Carra

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

unlimit
unlimit

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

Related Questions