简体   繁体   中英

Truncate number of digit of double value in C#

How can i truncate the leading digit of double value in C#,I have tried Math.Round(doublevalue,2) but not giving the require result. and i didn't find any other method in Math class.

For example i have value 12.123456789 and i only need 12.12.

EDIT: It's been pointed out that these approaches round the value instead of truncating . It's hard to genuinely truncate a double value because it's not really in the right base... but truncating a decimal value is more feasible.

You should use an appropriate format string, either custom or standard , eg

string x = d.ToString("0.00");

or

string x = d.ToString("F2");

It's worth being aware that a double value itself doesn't "know" how many decimal places it has. It's only when you convert it to a string that it really makes sense to do so. Using Math.Round will get the closest double value to x.xx00000 (if you see what I mean) but it almost certainly won't be the exact value x.xx00000 due to the way binary floating point types work.

If you need this for anything other than string formatting, you should consider using decimal instead. What does the value actually represent?

I have articles on binary floating point and decimal floating point in .NET which you may find useful.

What have you tried? It works as expected for me:

double original = 12.123456789;

double truncated = Math.Truncate(original * 100) / 100;

Console.WriteLine(truncated);    // displays 12.12

This code....

double x = 12.123456789;
Console.WriteLine(x);
x = Math.Round(x, 2);
Console.WriteLine(x);

Returns this....

12.123456789
12.12

What is your desired result that is different?

If you want to keep the value as a double, and just strip of any digits after the second decimal place and not actually round the number then you can simply subtract 0.005 from your number so that round will then work. For example.

double x = 98.7654321;
Console.WriteLine(x);
double y = Math.Round(x - 0.005, 2);
Console.WriteLine(y);

Produces this...

98.7654321
98.76

This could work (although not tested):

public 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);
double original = 12.123456789;  

double truncated = Truncate(original, 2);  

Console.WriteLine(truncated.ToString());
// or 
// Console.WriteLine(truncated.ToString("0.00"));
// or 
// Console.WriteLine(Truncate(original, 2).ToString("0.00"));


public static double Truncate(double value, int precision)
{
    return Math.Truncate(value * Math.Pow(10, precision)) / Math.Pow(10, precision);
}

I'm sure there's something more .netty out there but why not just:-

double truncVal = Math.Truncate(val * 100) / 100;
double remainder = val-truncVal;

How about:

double num = 12.12890;
double truncatedNum = ((int)(num * 100))/100.00;

There are a lot of answers using Math.Truncate(double). However, the approach using Math.Truncate(double) can lead to incorrect results. For instance, it will return 5.01 truncating 5.02, because multiplying of double values doesn't work precisely and 5.02*100=501.99999999999994

5.02*100=501.99999999999994

If you really need this precision, consider, converting to Decimal before truncating.

public static double Truncate(double value, int precision)
{
    decimal power = (decimal)Math.Pow(10, precision);
    return (double)(Math.Truncate((decimal)value * power) / power);
}

Still, this approach is ~10 times slower.

object number = 12.123345534;   
string.Format({"0:00"},number.ToString());

If you are looking to have two points after the decimal without rounding the number, the following should work

string doubleString = doublevalue.ToString("0.0000"); //To ensure we have a sufficiently lengthed string to avoid index issues
Console.Writeline(doubleString
             .Substring(0, (doubleString.IndexOf(".") +1) +2)); 

The second parameter of substring is the count, and IndexOf returns to zero-based index, so we have to add one to that before we add the 2 decimal values.

This answer is assuming that the value should NOT be rounded

For vb.net use this extension:

Imports System.Runtime.CompilerServices

Module DoubleExtensions

    <Extension()>
    Public Function Truncate(dValue As Double, digits As Integer)

        Dim factor As Integer
        factor = Math.Pow(10, digits)

        Return Math.Truncate(dValue * factor) / factor

    End Function
End Module

This maybe for decimal? I wrote my own coz of struggling to find answers online. This code is probably not fullproof as I lack the experience to fullproof it. Will eventually rebuild this method into something simple and awesome to get the job done in fewer steps with overall robustness improved too. You could easily convert it to take an input for spacing count. but I can not guarentee that it will function properly with other than two dec. Does not like plain inputs.. It seems to like a few 000.000 to work with as I am processing weight with 0000.000's coming through. Also, rounding prices with this after being calculated.

private decimal TruncateToTwoDecimals(string value)
        {

            int error_ReturnZeroIfThisIsOne = 0;
            int tempArrayLength = value.Length;
            char[] tempArray = new char[tempArrayLength];

            int startCount = 0; //starts the counter when it hits punctuation
            int newCounter = 0; //counts twice to ensure only two decimal places after the comma/period
            int nextArraySize = 1; //gets the size spec ready for the return array/next array (needs to be + 1)

            int tempArrayCurrentIndex = 0;
            foreach (Char thisChar in value)
            {
                tempArray[tempArrayCurrentIndex] = thisChar;
                tempArrayCurrentIndex++;
            }


            for (int i = 0; i < tempArrayLength; i++)
            {

                if (tempArray[i].ToString() == "," || tempArray[i].ToString() == ".")
                {
                    startCount = 1;
                }
                if (startCount == 1)
                {
                    newCounter++;
                }


                if (newCounter > 2)
                {
                    break;
                }
                nextArraySize++;
            }

            char[] returnArray = new char[nextArraySize];
            int tempErrorCheckBelow = 0;
            for (int i = 0; i < nextArraySize; i++)
            {


                try
                {
                    returnArray[i] = tempArray[i]; //left array will read [i] till the spot in right array where second decimal and ignore the rest. snip snip
                }
                catch (Exception)
                {
                    if (tempErrorCheckBelow == 2)
                    {
                        MessageBox.Show("OutOfBounds", "Error_ArrayIndex Out Of Bounds @TTTD");
                    }
                    returnArray[i] = Convert.ToChar("0");
                    tempErrorCheckBelow++;
                }

            }

            if (tempArrayLength < 1)
            {

                error_ReturnZeroIfThisIsOne++;

                string tempString = "0.0";
                try
                {
                    decimal tempDecimal = Decimal.Parse(tempString);
                    return tempDecimal;
                }
                catch (Exception)
                {

                    MessageBox.Show("Error_input String received Incorrect Format @TTTD");
                    return 0.00m;
                }
            }
            else
            {

                error_ReturnZeroIfThisIsOne++;

                string tempString = " ";
                tempString = new string(returnArray);
                try
                {
                    decimal tempDecimal = Decimal.Parse(tempString);
                    return tempDecimal;
                }
                catch (Exception)
                {
                    MessageBox.Show("Error_inputString _0_ @TTTD");
                    return 0m;

                }
            }



        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM