Chuyển đổi kép sang chuỗi không có ký hiệu khoa học


81

Làm cách nào để chuyển đổi một kép thành biểu diễn chuỗi dấu phẩy động không có ký hiệu khoa học trong .NET Framework?

Mẫu "nhỏ" (số hiệu quả có thể có kích thước bất kỳ, chẳng hạn như 1.5E200hoặc 1e-200):

3248971234698200000000000000000000000000000000
0.00000000000000000000000000000000000023897356978234562

Không có định dạng số tiêu chuẩn nào giống như thế này và định dạng tùy chỉnh dường như cũng không cho phép có một số chữ số mở sau dấu phân tách thập phân.

Đây không phải là bản sao của Cách chuyển đổi đôi sang chuỗi mà không có sức mạnh thành biểu diễn 10 (E-05) vì các câu trả lời được đưa ra không giải quyết được vấn đề trong tầm tay. Giải pháp được chấp nhận trong câu hỏi này là sử dụng một điểm cố định (chẳng hạn như 20 chữ số), đây không phải là điều tôi muốn. Định dạng điểm cố định và cắt bớt số 0 thừa cũng không giải quyết được vấn đề vì chiều rộng tối đa cho chiều rộng cố định là 99 ký tự.

Lưu ý: giải pháp phải xử lý chính xác các định dạng số tùy chỉnh (ví dụ: dấu phân tách thập phân khác, tùy thuộc vào thông tin văn hóa).

Chỉnh sửa: Câu hỏi thực sự chỉ là về việc bác bỏ những con số đã nói ở trên. Tôi biết cách hoạt động của số dấu phẩy động và những số nào có thể được sử dụng và tính toán với chúng.


1
bạn có một giải pháp cho câu hỏi này bây giờ?
Kira

@Và, có hai giải pháp hoạt động (Paul Sasik và của tôi) ngay cả khi chúng không quá "tốt" (thông qua thao tác chuỗi).
Lucero

Câu trả lời:


41

Đối với một giải pháp có mục đích chung¹, bạn cần bảo tồn 339 vị trí:

doubleValue.ToString("0." + new string('#', 339))

Số chữ số thập phân khác 0 tối đa là 16. 15 ở bên phải của dấu thập phân. Số mũ có thể di chuyển 15 chữ số đó tối đa 324 vị trí sang bên phải. ( Xem phạm vi và độ chính xác. )

Nó hoạt động cho double.Epsilon, double.MinValue, double.MaxValue, và bất cứ điều gì ở giữa.

Hiệu suất sẽ lớn hơn nhiều so với các giải pháp thao tác chuỗi / regex vì tất cả công việc định dạng và chuỗi được thực hiện trong một lần chuyển bằng mã CLR không được quản lý. Ngoài ra, mã đơn giản hơn nhiều để chứng minh là đúng.

Để dễ sử dụng và thậm chí có hiệu suất tốt hơn, hãy đặt nó thành một hằng số:

public static class FormatStrings
{
    public const string DoubleFixedPoint = "0.###################################################################################################################################################################################################################################################################################################################################################";
}

¹ Cập nhật: Tôi đã nói nhầm rằng đây cũng là một giải pháp không mất dữ liệu. Thực tế là không, vì ToStringmàn hình bình thường của nó làm tròn cho tất cả các định dạng ngoại trừ r. Ví dụ trực tiếp. Cảm ơn, @Loathing! Vui lòng xem câu trả lời của Lothing nếu bạn cần khả năng làm tròn theo ký hiệu điểm cố định (tức là nếu bạn đang sử dụng .ToString("r")ngày hôm nay).


Đẹp và khá ngắn, nhưng nếu bạn không cần giá trị cực lớn, bạn có thể làm nhanh hơn 10 lần. Xem câu trả lời của tôi: stackoverflow.com/a/36204442/143684
ygoe

Cảm ơn bạn, hoạt động hoàn hảo. Bạn là một con người tuyệt vời. Đã ủng hộ.
Snoop

1
Giải pháp này không phải là "thất bại". Ví dụ: String t1 = (0.0001/7).ToString("0." + new string('#', 339)); // 0.0000142857142857143so với: Độ String t2 = (0.0001/7).ToString("r"); // 1.4285714285714287E-05chính xác bị mất ở các chữ số thập phân cuối cùng.
Loathing

30

Tôi đã gặp sự cố tương tự và điều này đã hiệu quả với tôi:

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

F99 có thể là quá mức cần thiết, nhưng bạn sẽ có ý tưởng.


1
99 là không đủ, nó phải hoạt động cho cả trước và sau dấu phẩy.
Lucero

2
TrimEnd('0')là đủ, bởi vì charmảng là params. Có nghĩa là, bất kỳ chars được chuyển đến TrimEndsẽ được tự động nhóm thành một mảng.
Grault

99 là không đủ cho một giải pháp có mục đích chung. doubleValue.ToString("0." + new string('#', 339))là không mất mát. So sánh các phương pháp này bằng cách sử dụng giá trị double.Epsilon.
jnm2

20

Đây là một giải pháp phân tích cú pháp chuỗi trong đó số nguồn (kép) được chuyển đổi thành một chuỗi và được phân tích cú pháp thành các thành phần cấu thành của nó. Sau đó, nó được tập hợp lại theo các quy tắc thành biểu diễn số có độ dài đầy đủ. Nó cũng tài khoản cho ngôn ngữ theo yêu cầu.

Cập nhật : Các bài kiểm tra chuyển đổi chỉ bao gồm các số nguyên có một chữ số, đây là tiêu chuẩn, nhưng thuật toán cũng hoạt động cho một số thứ như: 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();
    }
}

Huh. Thành thật mà nói, tôi nhận thấy rằng nó đã bị bỏ phiếu nên tôi đã không kiểm tra mã rất chặt chẽ. Tôi đã đọc nó ngay bây giờ và bạn đã đúng. Chúng đã kết thúc, tôi chỉ chọn không sử dụng RegEx trong quy trình của mình và đã phân tích cú pháp chuỗi của riêng tôi. Bạn đã thử nghiệm giải pháp này chưa? Đó là một ứng dụng bảng điều khiển hoàn chỉnh.
Paul Sasik

Chưa, sẽ làm điều đó sớm ...;)
Lucero

3
Cái này dễ đọc hơn, vì bạn không cần phải dò tìm regex.
Gregory

+1 LOL @ "grok the regex", tôi thích nó. tôi sẽ biến nó thành một phần trong quá trình phát triển bản địa của tôi! Cảm ơn.
Paul Sasik

Vâng, là Regex ít nhất đã độc đáo mang tên nhóm thay vì chỉ số unspecific trong một số mảng ...;)
Lucero

13

Bạn có thể truyền doubleđến decimalvà sau đó làm ToString().

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

Tôi chưa thực hiện kiểm tra hiệu suất nhanh hơn, truyền từ 64 bit doublesang 128 bit decimalhoặc một chuỗi định dạng gồm hơn 300 ký tự. Ồ, và có thể có lỗi tràn trong quá trình chuyển đổi, nhưng nếu các giá trị của bạn phù hợp với một giá trị, decimalthì điều này sẽ hoạt động tốt.

Cập nhật: Quá trình truyền có vẻ nhanh hơn rất nhiều. Sử dụng chuỗi định dạng đã chuẩn bị như được đưa ra trong câu trả lời khác, việc định dạng một triệu lần mất 2,3 giây và truyền chỉ 0,19 giây. Có thể lặp lại. Đó là 10x nhanh hơn . Bây giờ nó chỉ về phạm vi giá trị.


Rất tiếc, điều này không hoạt động đối với đặc điểm kỹ thuật đã cho của các số rất lớn hoặc nhỏ. ((decimal)(1e-200)).ToString()ví dụ trả về 0sai.
Lucero

1
Để công bằng và so sánh táo với táo, bạn nên so sánh phương pháp này với double.ToString("0.############################"). Theo thử nghiệm của tôi, của bạn chỉ nhanh hơn gấp 3 lần. Dù bằng cách nào thì nó cũng chỉ là một câu trả lời hợp lệ nếu bạn biết chắc rằng bạn không cần in các chữ số bên dưới 1e-28và số kép của bạn không lớn, cả hai đều không phải là ràng buộc trong câu hỏi ban đầu.
jnm2

2
Đây là một giải pháp khá tốt cho rằng bạn biết được phạm vi giá trị
Artur Udod

8

Đây là những gì tôi đã có cho đến nay, dường như hoạt động, nhưng có thể ai đó có giải pháp tốt hơn:

private static readonly Regex rxScientific = new Regex(@"^(?<sign>-?)(?<head>\d+)(\.(?<tail>\d*?)0*)?E(?<exponent>[+\-]\d+)$", RegexOptions.IgnoreCase|RegexOptions.ExplicitCapture|RegexOptions.CultureInvariant);

public static string ToFloatingPointString(double value) {
    return ToFloatingPointString(value, NumberFormatInfo.CurrentInfo);
}

public static string ToFloatingPointString(double value, NumberFormatInfo formatInfo) {
    string result = value.ToString("r", NumberFormatInfo.InvariantInfo);
    Match match = rxScientific.Match(result);
    if (match.Success) {
        Debug.WriteLine("Found scientific format: {0} => [{1}] [{2}] [{3}] [{4}]", result, match.Groups["sign"], match.Groups["head"], match.Groups["tail"], match.Groups["exponent"]);
        int exponent = int.Parse(match.Groups["exponent"].Value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
        StringBuilder builder = new StringBuilder(result.Length+Math.Abs(exponent));
        builder.Append(match.Groups["sign"].Value);
        if (exponent >= 0) {
            builder.Append(match.Groups["head"].Value);
            string tail = match.Groups["tail"].Value;
            if (exponent < tail.Length) {
                builder.Append(tail, 0, exponent);
                builder.Append(formatInfo.NumberDecimalSeparator);
                builder.Append(tail, exponent, tail.Length-exponent);
            } else {
                builder.Append(tail);
                builder.Append('0', exponent-tail.Length);
            }
        } else {
            builder.Append('0');
            builder.Append(formatInfo.NumberDecimalSeparator);
            builder.Append('0', (-exponent)-1);
            builder.Append(match.Groups["head"].Value);
            builder.Append(match.Groups["tail"].Value);
        }
        result = builder.ToString();
    }
    return result;
}

// test code
double x = 1.0;
for (int i = 0; i < 200; i++) {
    x /= 10;
}
Console.WriteLine(x);
Console.WriteLine(ToFloatingPointString(x));

-1 vì không cung cấp giải pháp cho tình huống sau (và nó không thể): double d1 = 1e-200; d = d + 1; ToFloatingPointString (d) chỉ trả về 1 ở đây. Không phải 1.000 ........... 000001.
JCasso

5
Việc thêm một vào một nhân đôi rất nhỏ chỉ là ý tưởng của bạn và không liên quan gì đến câu hỏi hiện tại. Nếu bạn chỉ chạy nó mà không có d = d + 1, bạn sẽ thấy rằng nó thực tế hiển thị 0,000 ..... 0001.
Lucero

Tìm cách tính 1e-200 trong thời gian chạy thay vì đặt giá trị "không đổi", tôi sẽ bỏ phiếu cho nó.
JCasso

2
Không vấn đề gì. double x = 1.0; for (int i = 0; i < 200; i++) x /= 10; Console.WriteLine(x);
Lucero

6
Đó là bởi vì trên thực tế chỉ có 15 chữ số là có ý nghĩa, nhưng bạn có thể "dịch" chúng với số mũ rất lớn hoặc rất nhỏ. Nhưng bạn không thể thêm một số rất nhỏ với một số lớn hơn khoảng 15 chữ số, vì làm như vậy vượt quá số chữ số có nghĩa và vì số lớn hơn có nghĩa hơn, nên phần nhỏ sẽ bị mất. Do đó, tính toán với các số trong một phạm vi tương tự (như thêm 1e-200 và 1e-200, hoặc 1 + 1, hoặc 1e200 + 1e200) hoạt động, nhưng trộn các giá trị như vậy sẽ dẫn đến làm tròn giá trị nhỏ hơn.
Lucero

4

Vấn đề khi sử dụng #.###...###hoặc F99là nó không bảo toàn độ chính xác ở các chữ số thập phân cuối cùng, ví dụ:

String t1 = (0.0001/7).ToString("0." + new string('#', 339)); // 0.0000142857142857143
String t2 = (0.0001/7).ToString("r");                         //      1.4285714285714287E-05

Vấn đề DecimalConverter.cslà nó chậm. Mã này giống với câu trả lời của Sasik, nhưng nhanh hơn gấp đôi. Phương pháp kiểm tra đơn vị ở dưới cùng.

public static class RoundTrip {

    private static String[] zeros = new String[1000];

    static RoundTrip() {
        for (int i = 0; i < zeros.Length; i++) {
            zeros[i] = new String('0', i);
        }
    }

    private static String ToRoundTrip(double value) {
        String str = value.ToString("r");
        int x = str.IndexOf('E');
        if (x < 0) return str;

        int x1 = x + 1;
        String exp = str.Substring(x1, str.Length - x1);
        int e = int.Parse(exp);

        String s = null;
        int numDecimals = 0;
        if (value < 0) {
            int len = x - 3;
            if (e >= 0) {
                if (len > 0) {
                    s = str.Substring(0, 2) + str.Substring(3, len);
                    numDecimals = len;
                }
                else
                    s = str.Substring(0, 2);
            }
            else {
                // remove the leading minus sign
                if (len > 0) {
                    s = str.Substring(1, 1) + str.Substring(3, len);
                    numDecimals = len;
                }
                else
                    s = str.Substring(1, 1);
            }
        }
        else {
            int len = x - 2;
            if (len > 0) {
                s = str[0] + str.Substring(2, len);
                numDecimals = len;
            }
            else
                s = str[0].ToString();
        }

        if (e >= 0) {
            e = e - numDecimals;
            String z = (e < zeros.Length ? zeros[e] : new String('0', e));
            s = s + z;
        }
        else {
            e = (-e - 1);
            String z = (e < zeros.Length ? zeros[e] : new String('0', e));
            if (value < 0)
                s = "-0." + z + s;
            else
                s = "0." + z + s;
        }

        return s;
    }

    private static void RoundTripUnitTest() {
        StringBuilder sb33 = new StringBuilder();
        double[] values = new [] { 123450000000000000.0, 1.0 / 7, 10000000000.0/7, 100000000000000000.0/7, 0.001/7, 0.0001/7, 100000000000000000.0, 0.00000000001,
         1.23e-2, 1.234e-5, 1.2345E-10, 1.23456E-20, 5E-20, 1.23E+2, 1.234e5, 1.2345E10, -7.576E-05, 1.23456e20, 5e+20, 9.1093822E-31, 5.9736e24, double.Epsilon };

        foreach (int sign in new [] { 1, -1 }) {
            foreach (double val in values) {
                double val2 = sign * val;
                String s1 = val2.ToString("r");
                String s2 = ToRoundTrip(val2);

                double val2_ = double.Parse(s2);
                double diff = Math.Abs(val2 - val2_);
                if (diff != 0) {
                    throw new Exception("Value {0} did not pass ToRoundTrip.".Format2(val.ToString("r")));
                }
                sb33.AppendLine(s1);
                sb33.AppendLine(s2);
                sb33.AppendLine();
            }
        }
    }
}

3

Giải pháp dựa trên Logarit bắt buộc. Lưu ý rằng giải pháp này, vì nó liên quan đến làm toán, có thể làm giảm độ chính xác của số của bạn một chút. Không được thử nghiệm nhiều.

private static string DoubleToLongString(double x)
{
    int shift = (int)Math.Log10(x);
    if (Math.Abs(shift) <= 2)
    {
        return x.ToString();
    }

    if (shift < 0)
    {
        double y = x * Math.Pow(10, -shift);
        return "0.".PadRight(-shift + 2, '0') + y.ToString().Substring(2);
    }
    else
    {
        double y = x * Math.Pow(10, 2 - shift);
        return y + "".PadRight(shift - 2, '0');
    }
}

Chỉnh sửa: Nếu dấu thập phân vượt qua phần khác 0 của số, thuật toán này sẽ thất bại thảm hại. Tôi đã cố gắng vì đơn giản và đã đi quá xa.


Cảm ơn bạn đã đóng góp ý kiến, tôi sẽ cố gắng triển khai một giải pháp hoạt động đầy đủ như thế này và so sánh nó với giải pháp của tôi.
Lucero

3

Ngày xưa khi chúng ta phải viết các bộ định dạng của riêng mình, chúng ta sẽ tách riêng phần định trị và số mũ và định dạng chúng một cách riêng biệt.

Trong bài viết này của Jon Skeet ( https://csharpindepth.com/articles/FloatingPoint ), anh ấy cung cấp một liên kết đến quy trình DoubleConverter.cs của mình để thực hiện chính xác những gì bạn muốn. Skeet cũng đề cập đến điều này khi trích xuất phần định trị và số mũ từ nhân đôi trong c # .


Cảm ơn vì liên kết, tôi đã thử mã từ Jon rồi, tuy nhiên đối với mục đích của tôi, nó hơi chính xác; ví dụ, 0.1 không hiển thị như 0.1 (đó là chính xác về mặt kỹ thuật, nhưng không phải những gì tôi cần) ...
Lucero

Vâng, nhưng bạn thấy đấy, toàn bộ mã của Jon là hiển thị con số CHÍNH XÁC và điều này hơi quá đối với trường hợp của tôi. Làm tròn như được thực hiện bởi thời gian chạy khi thực hiện ToString () phù hợp với tôi và đó có lẽ cũng là lý do tại sao hầu hết các giải pháp được đề xuất ở đây sử dụng ToString () làm cơ sở để xử lý thêm.
Lucero

Xin chào! Tôi đến đây từ 10 năm sau để cho bạn biết rằng siêu liên kết tới bài báo của Jon đã bị hỏng.
Nick Vaccaro,

2

Tôi vừa ứng biến mã ở trên để làm cho nó hoạt động với các giá trị hàm mũ âm.

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);
                }
            }
        }
    }
}

Mã này lấy một thư mục đầu vào và dựa trên dấu phân cách chuyển đổi tất cả các giá trị trong ký hiệu khoa học sang định dạng số.

Cảm ơn


1

hãy thử cái này:

public static string DoubleToFullString(double value, 
                                        NumberFormatInfo formatInfo)
{
    string[] valueExpSplit;
    string result, decimalSeparator;
    int indexOfDecimalSeparator, exp;

    valueExpSplit = value.ToString("r", formatInfo)
                         .ToUpper()
                         .Split(new char[] { 'E' });

    if (valueExpSplit.Length > 1)
    {
        result = valueExpSplit[0];
        exp = int.Parse(valueExpSplit[1]);
        decimalSeparator = formatInfo.NumberDecimalSeparator;

        if ((indexOfDecimalSeparator 
             = valueExpSplit[0].IndexOf(decimalSeparator)) > -1)
        {
            exp -= (result.Length - indexOfDecimalSeparator - 1);
            result = result.Replace(decimalSeparator, "");
        }

        if (exp >= 0) result += new string('0', Math.Abs(exp));
        else
        {
            exp = Math.Abs(exp);
            if (exp >= result.Length)
            {
                result = "0." + new string('0', exp - result.Length) 
                             + result;
            }
            else
            {
                result = result.Insert(result.Length - exp, decimalSeparator);
            }
        }
    }
    else result = valueExpSplit[0];

    return result;
}

0

Là hàng triệu lập trình viên trên toàn thế giới, bạn nên thử tìm kiếm nếu ai đó đã gặp phải vấn đề của bạn. Đôi khi có những giải pháp là rác, điều đó có nghĩa là đã đến lúc bạn phải viết bài của riêng bạn và đôi khi có những giải pháp tuyệt vời, chẳng hạn như sau:

http://www.yoda.arachsys.com/csharp/DoubleConverter.cs

(chi tiết: http://www.yoda.arachsys.com/csharp/floatingpoint.html )


1
Điều này tương tự như đã được đăng bởi ebpower, xem các ý kiến đó ...;)
Lucero

0
string strdScaleFactor = dScaleFactor.ToString(); // where dScaleFactor = 3.531467E-05

decimal decimalScaleFactor = Decimal.Parse(strdScaleFactor, System.Globalization.NumberStyles.Float);

Bạn có thể giải thích ngắn gọn mã này làm gì và nó khác với 15 câu trả lời khác như thế nào?
JJJ

Chào mừng bạn đến với Stack Overflow! Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. Cũng vui lòng cố gắng không chèn mã của bạn bằng các nhận xét giải thích, điều này làm giảm khả năng đọc của cả mã và giải thích!
thuyền kayess

-1

Tôi có thể sai, nhưng nó không phải là như thế này?

data.ToString("n");

http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx


Thấy câu trả lời của bạn, tôi chắc đã hiểu sai câu hỏi của bạn, xin lỗi.
csharptest.net

Không, đầu tiên tôi không muốn dấu phân cách nghìn và thứ hai dường như luôn có một số chữ số cố định sau dấu phẩy. Xem thêm trợ giúp MSDN cho định dạng N: msdn.microsoft.com/en-us/library/dwhawy9k.aspx#NFormatString
Lucero

Bạn cũng có thể thêm nhiều hơn sau chữ số thập phân (tức là "n8" hoặc "n50", v.v.).
BrainSlugs83

-1

Chỉ để xây dựng dựa trên những gì jcasso đã nói, những gì bạn có thể làm là điều chỉnh giá trị kép của mình bằng cách thay đổi số mũ sao cho định dạng yêu thích của bạn sẽ làm điều đó cho bạn, áp dụng định dạng và thay thế kết quả bằng các số không để bù đắp cho việc điều chỉnh.


Số mũ trong các số dấu phẩy động IEEE là 2 cơ số, nhưng các số thập phân là 10 cơ số. Do đó, điều này không hoạt động. Đây cũng là lý do tại sao bạn không thể lưu trữ 0,1 dưới dạng giá trị chính xác trong một nhân đôi. Hoặc vui lòng chỉ cung cấp một số mẫu (mã) nếu bạn nghĩ rằng tôi đã hiểu sai câu trả lời của bạn.
Lucero

-1

tôi nghĩ bạn chỉ cần sử dụng IFormat với

ToString(doubleVar, System.Globalization.NumberStyles.Number)

thí dụ:

double d = double.MaxValue;
string s = d.ToString(d, System.Globalization.NumberStyles.Number);

6
Điều đó thậm chí không biên dịch, bạn có thể đăng một cái gì đó mà biên dịch?
Lucero

-1

Giải pháp của tôi là sử dụng các định dạng tùy chỉnh. thử đi:

double d;
d = 1234.12341234;
d.ToString("#########0.#########");

2
Hãy thử với các số kiểm tra tôi đã đưa ra ở trên: d = 1.5E200d = 1E-200. Chuỗi kết quả phải có gần 200 0ký tự trong đó, nếu không giải pháp của bạn không hoạt động.
Lucero

9 chữ số thập phân là không đủ cho một giải pháp có mục đích chung. doubleValue.ToString("0." + new string('#', 339))là không mất mát. So sánh các phương pháp này bằng cách sử dụng giá trị double.Epsilon.
jnm2

-1

Cái này làm việc tốt cho tôi...

double number = 1.5E+200;
string s = number.ToString("#");

//Output: "150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

1
Có, nó hoạt động với số lượng lớn, nhưng không hoạt động với bất kỳ thứ gì đằng sau dấu phẩy, đặc biệt là không phải thứ gì đó tương tự 1.5e-200.
Lucero
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.