Double to string conversion without scientific notation

前端 未结 17 1321
無奈伤痛
無奈伤痛 2020-11-22 15:33

How to convert a double into a floating-point string representation without scientific notation in the .NET Framework?

\"Small\" samples (effective numbers may be of

相关标签:
17条回答
  • 2020-11-22 16:09

    This works fine for me...

    double number = 1.5E+200;
    string s = number.ToString("#");
    
    //Output: "150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    
    0 讨论(0)
  • 2020-11-22 16:10

    This is a string parsing solution where the source number (double) is converted into a string and parsed into its constituent components. It is then reassembled by rules into the full-length numeric representation. It also accounts for locale as requested.

    Update: The tests of the conversions only include single-digit whole numbers, which is the norm, but the algorithm also works for something like: 239483.340901e-20

    using System;
    using System.Text;
    using System.Globalization;
    using System.Threading;
    
    public class MyClass
    {
        public static void Main()
        {
            Console.WriteLine(ToLongString(1.23e-2));            
            Console.WriteLine(ToLongString(1.234e-5));           // 0.00010234
            Console.WriteLine(ToLongString(1.2345E-10));         // 0.00000001002345
            Console.WriteLine(ToLongString(1.23456E-20));        // 0.00000000000000000100023456
            Console.WriteLine(ToLongString(5E-20));
            Console.WriteLine("");
            Console.WriteLine(ToLongString(1.23E+2));            // 123
            Console.WriteLine(ToLongString(1.234e5));            // 1023400
            Console.WriteLine(ToLongString(1.2345E10));          // 1002345000000
            Console.WriteLine(ToLongString(-7.576E-05));         // -0.00007576
            Console.WriteLine(ToLongString(1.23456e20));
            Console.WriteLine(ToLongString(5e+20));
            Console.WriteLine("");
            Console.WriteLine(ToLongString(9.1093822E-31));        // mass of an electron
            Console.WriteLine(ToLongString(5.9736e24));            // mass of the earth 
    
            Console.ReadLine();
        }
    
        private static string ToLongString(double input)
        {
            string strOrig = input.ToString();
            string str = strOrig.ToUpper();
    
            // if string representation was collapsed from scientific notation, just return it:
            if (!str.Contains("E")) return strOrig;
    
            bool negativeNumber = false;
    
            if (str[0] == '-')
            {
                str = str.Remove(0, 1);
                negativeNumber = true;
            }
    
            string sep = Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;
            char decSeparator = sep.ToCharArray()[0];
    
            string[] exponentParts = str.Split('E');
            string[] decimalParts = exponentParts[0].Split(decSeparator);
    
            // fix missing decimal point:
            if (decimalParts.Length==1) decimalParts = new string[]{exponentParts[0],"0"};
    
            int exponentValue = int.Parse(exponentParts[1]);
    
            string newNumber = decimalParts[0] + decimalParts[1];
    
            string result;
    
            if (exponentValue > 0)
            {
                result = 
                    newNumber + 
                    GetZeros(exponentValue - decimalParts[1].Length);
            }
            else // negative exponent
            {
                result = 
                    "0" + 
                    decSeparator + 
                    GetZeros(exponentValue + decimalParts[0].Length) + 
                    newNumber;
    
                result = result.TrimEnd('0');
            }
    
            if (negativeNumber)
                result = "-" + result;
    
            return result;
        }
    
        private static string GetZeros(int zeroCount)
        {
            if (zeroCount < 0) 
                zeroCount = Math.Abs(zeroCount);
    
            StringBuilder sb = new StringBuilder();
    
            for (int i = 0; i < zeroCount; i++) sb.Append("0");    
    
            return sb.ToString();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:10

    You could cast the double to decimal and then do ToString().

    (0.000000005).ToString()   // 5E-09
    ((decimal)(0.000000005)).ToString()   // 0,000000005
    

    I haven't done performance testing which is faster, casting from 64-bit double to 128-bit decimal or a format string of over 300 chars. Oh, and there might possibly be overflow errors during conversion, but if your values fit a decimal this should work fine.

    Update: The casting seems to be a lot faster. Using a prepared format string as given in the other answer, formatting a million times takes 2.3 seconds and casting only 0.19 seconds. Repeatable. That's 10x faster. Now it's only about the value range.

    0 讨论(0)
  • 2020-11-22 16:11

    I have just improvised on the code above to make it work for negative exponential values.

    using System;
    using System.Text.RegularExpressions;
    using System.IO;
    using System.Text;
    using System.Threading;
    
    namespace ConvertNumbersInScientificNotationToPlainNumbers
    {
        class Program
        {
            private static string ToLongString(double input)
            {
                string str = input.ToString(System.Globalization.CultureInfo.InvariantCulture);
    
                // if string representation was collapsed from scientific notation, just return it:
                if (!str.Contains("E")) return str;
    
                var positive = true;
                if (input < 0)
                {
                    positive = false;
                }
    
                string sep = Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;
                char decSeparator = sep.ToCharArray()[0];
    
                string[] exponentParts = str.Split('E');
                string[] decimalParts = exponentParts[0].Split(decSeparator);
    
                // fix missing decimal point:
                if (decimalParts.Length == 1) decimalParts = new string[] { exponentParts[0], "0" };
    
                int exponentValue = int.Parse(exponentParts[1]);
    
                string newNumber = decimalParts[0].Replace("-", "").
                    Replace("+", "") + decimalParts[1];
    
                string result;
    
                if (exponentValue > 0)
                {
                    if (positive)
                        result =
                            newNumber +
                            GetZeros(exponentValue - decimalParts[1].Length);
                    else
    
                        result = "-" +
                         newNumber +
                         GetZeros(exponentValue - decimalParts[1].Length);
    
    
                }
                else // negative exponent
                {
                    if (positive)
                        result =
                            "0" +
                            decSeparator +
                            GetZeros(exponentValue + decimalParts[0].Replace("-", "").
                                       Replace("+", "").Length) + newNumber;
                    else
                        result =
                        "-0" +
                        decSeparator +
                        GetZeros(exponentValue + decimalParts[0].Replace("-", "").
                                 Replace("+", "").Length) + newNumber;
    
                    result = result.TrimEnd('0');
                }
                float temp = 0.00F;
    
                if (float.TryParse(result, out temp))
                {
                    return result;
                }
                throw new Exception();
            }
    
            private static string GetZeros(int zeroCount)
            {
                if (zeroCount < 0)
                    zeroCount = Math.Abs(zeroCount);
    
                StringBuilder sb = new StringBuilder();
    
                for (int i = 0; i < zeroCount; i++) sb.Append("0");
    
                return sb.ToString();
            }
    
            public static void Main(string[] args)
            {
                //Get Input Directory.
                Console.WriteLine(@"Enter the Input Directory");
                var readLine = Console.ReadLine();
                if (readLine == null)
                {
                    Console.WriteLine(@"Enter the input path properly.");
                    return;
                }
                var pathToInputDirectory = readLine.Trim();
    
                //Get Output Directory.
                Console.WriteLine(@"Enter the Output Directory");
                readLine = Console.ReadLine();
                if (readLine == null)
                {
                    Console.WriteLine(@"Enter the output path properly.");
                    return;
                }
                var pathToOutputDirectory = readLine.Trim();
    
                //Get Delimiter.
                Console.WriteLine("Enter the delimiter;");
                var columnDelimiter = (char)Console.Read();
    
                //Loop over all files in the directory.
                foreach (var inputFileName in Directory.GetFiles(pathToInputDirectory))
                {
                    var outputFileWithouthNumbersInScientificNotation = string.Empty;
                    Console.WriteLine("Started operation on File : " + inputFileName);
    
                    if (File.Exists(inputFileName))
                    {
                        // Read the file
                        using (var file = new StreamReader(inputFileName))
                        {
                            string line;
                            while ((line = file.ReadLine()) != null)
                            {
                                String[] columns = line.Split(columnDelimiter);
                                var duplicateLine = string.Empty;
                                int lengthOfColumns = columns.Length;
                                int counter = 1;
                                foreach (var column in columns)
                                {
                                    var columnDuplicate = column;
                                    try
                                    {
                                        if (Regex.IsMatch(columnDuplicate.Trim(),
                                                          @"^[+-]?[0-9]+(\.[0-9]+)?[E]([+-]?[0-9]+)$",
                                                          RegexOptions.IgnoreCase))
                                        {
                                            Console.WriteLine("Regular expression matched for this :" + column);
    
                                            columnDuplicate = ToLongString(Double.Parse
                                                                               (column,
                                                                                System.Globalization.NumberStyles.Float));
    
                                            Console.WriteLine("Converted this no in scientific notation " +
                                                              "" + column + "  to this number " +
                                                              columnDuplicate);
                                        }
                                    }
                                    catch (Exception)
                                    {
    
                                    }
                                    duplicateLine = duplicateLine + columnDuplicate;
    
                                    if (counter != lengthOfColumns)
                                    {
                                        duplicateLine = duplicateLine + columnDelimiter.ToString();
                                    }
                                    counter++;
                                }
                                duplicateLine = duplicateLine + Environment.NewLine;
                                outputFileWithouthNumbersInScientificNotation = outputFileWithouthNumbersInScientificNotation + duplicateLine;
                            }
    
                            file.Close();
                        }
    
                        var outputFilePathWithoutNumbersInScientificNotation
                            = Path.Combine(pathToOutputDirectory, Path.GetFileName(inputFileName));
    
                        //Create Directory If it does not exist.
                        if (!Directory.Exists(pathToOutputDirectory))
                            Directory.CreateDirectory(pathToOutputDirectory);
    
                        using (var outputFile =
                            new StreamWriter(outputFilePathWithoutNumbersInScientificNotation))
                        {
                            outputFile.Write(outputFileWithouthNumbersInScientificNotation);
                            outputFile.Close();
                        }
    
                        Console.WriteLine("The transformed file is here :" +
                            outputFilePathWithoutNumbersInScientificNotation);
                    }
                }
            }
        }
    }
    

    This code takes an input directory and based on the delimiter converts all values in scientific notation to numeric format.

    Thanks

    0 讨论(0)
  • 2020-11-22 16:12

    I had a similar problem and this worked for me:

    doubleValue.ToString("F99").TrimEnd('0')
    

    F99 may be overkill, but you get the idea.

    0 讨论(0)
提交回复
热议问题