과학적 표기법없이 Double에서 문자열로 변환


81

.NET Framework에서 과학적 표기법없이 double을 부동 소수점 문자열 표현으로 변환하는 방법은 무엇입니까?

"작은"샘플 (유효 숫자는 1.5E200또는 등의 크기가 될 수 있음 1e-200) :

3248971234698200000000000000000000000000000000
0.00000000000000000000000000000000000023897356978234562

의 없음 표준 숫자 형식은 다음과 같이 없습니다 및 사용자 지정 형식은 또한 소수 구분 자리수의 오픈 수를 가지고 허용하지 않는 것 같습니다.

주어진 대답이 당면한 문제를 해결 하지 하기 때문에 이것은 10의 거듭 제곱 표현 (E-05)없이 double을 문자열로 변환하는 방법 의 중복이 아닙니다 . 이 질문에서 허용되는 해결책은 내가 원하는 것이 아닌 고정 소수점 (예 : 20 자리)을 사용하는 것입니다. 고정 소수점 서식을 지정하고 중복 0을 트리밍해도 고정 너비의 최대 너비가 99 자이기 때문에 문제가 해결되지 않습니다.

참고 : 솔루션은 사용자 지정 숫자 형식 (예 : 문화 정보에 따라 다른 소수 구분 기호)을 올바르게 처리해야합니다.

편집 : 질문은 실제로 위에서 언급 한 숫자를 대체하는 것에 관한 것입니다. 나는 부동 소수점 숫자가 어떻게 작동하는지, 그리고 그것들로 어떤 숫자를 사용하고 계산할 수 있는지 알고 있습니다.


1
지금이 질문에 대한 해결책이 있습니까?
Kira

@Anand, 지나치게 "좋은"(문자열 조작을 거치는)이 아니더라도 작동하는 두 가지 솔루션이 있습니다 (Paul Sasik과 내).
Lucero

답변:


41

범용 ¹ 솔루션의 경우 339 개의 장소를 보존해야합니다.

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

0이 아닌 십진수의 최대 수는 16입니다. 15는 소수점 오른쪽에 있습니다. 지수는이 15 자리 숫자를 오른쪽으로 최대 324 자리까지 이동할 수 있습니다. ( 범위와 정밀도를 참조하십시오. )

그것은 작동 double.Epsilon, double.MinValue, double.MaxValue그 사이에, 아무것도.

모든 서식 및 문자열 작업이 관리되지 않는 CLR 코드에 의해 한 번에 수행되므로 성능은 정규식 / 문자열 조작 솔루션보다 훨씬 큽니다. 또한 코드가 정확하다는 것을 증명하는 것이 훨씬 간단합니다.

사용 편의성과 더 나은 성능을 위해 일정하게 만드십시오.

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

¹ 업데이트 : 이 역시 무손실 솔루션이라고 잘못 말했습니다. 때문에 사실이 아니다 ToString제외한 모든 포맷의 일반 표시 라운딩을한다 r. 라이브 예. 감사합니다, @Loathing! 고정 소수점 표기법으로 왕복하는 기능이 필요하면 Lothing의 답변을 참조하십시오 (즉, .ToString("r")오늘 사용하는 경우 ).


훌륭하고 매우 짧지 만 매우 큰 값이 필요하지 않은 경우 10 배 더 빠르게 수행 할 수 있습니다. 내 대답보기 : stackoverflow.com/a/36204442/143684
ygoe

감사합니다. 완벽하게 작동했습니다. 당신은 멋진 인간입니다. 찬성.
Snoop

1
이 솔루션은 "무손실"이 아닙니다. 예 : String t1 = (0.0001/7).ToString("0." + new string('#', 339)); // 0.0000142857142857143대 : String t2 = (0.0001/7).ToString("r"); // 1.4285714285714287E-05소수점 끝자리에서 정밀도가 손실됩니다.
Loathing

30

비슷한 문제가 있었고 이것은 나를 위해 일했습니다.

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

F99는 과잉 일 수 있지만 아이디어를 얻습니다.


1
99 충분하지 않습니다, 그리고 그것은 이전과 쉼표 뒤에 모두를위한 일에 있습니다.
Lucero

2
TrimEnd('0')char배열이 이므로 충분 params합니다. 즉, char전달 TrimEnd된 모든는 자동으로 배열로 그룹화됩니다.
Grault

99는 범용 솔루션으로 는 충분 하지 않습니다 . doubleValue.ToString("0." + new string('#', 339))무손실입니다. 값을 사용하여 이러한 방법을 비교하십시오 double.Epsilon.
jnm2

20

이것은 소스 번호 (double)가 문자열로 변환되고 구성 요소로 구문 분석되는 문자열 구문 분석 솔루션입니다. 그런 다음 규칙에 의해 전체 길이 숫자 표현으로 재 조립됩니다. 또한 요청 된 로케일을 고려합니다.

업데이트 : 변환 테스트에는 일반적인 한 자리 정수만 포함되지만 알고리즘은 다음과 같은 경우에도 작동합니다. 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();
    }
}

허. 솔직히, 나는 그것이 투표에서 떨어 졌다는 것을 알았 기 때문에 코드를 자세히 조사하지 않았습니다. 방금 읽었는데 당신 말이 맞아요. 그들은 가깝고, 내 프로세스에서 RegEx를 사용하지 않기로 선택하고 자체 문자열 구문 분석을 수행했습니다. 이 솔루션을 테스트 했습니까? 완전한 콘솔 앱입니다.
Paul Sasik

아직, ... 곧 그것을 할 것)
루세

3
이것은 정규식을 찾을 필요가 없기 때문에 더 쉽게 읽을 수 있습니다.
Gregory

+1 LOL @ "grok the regex"나는 그것을 좋아한다. 나는 그것을 내 개발의 일부로 만들 것입니다! 감사.
Paul Sasik

음, Regex 하나는 적어도 일부 배열에서 불특정 인덱스 대신 멋지게 명명 된 그룹을 가지고 있습니다 ...;)
Lucero

13

당신은 캐스팅 수 doubledecimal다음을 수행 ToString().

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

64 비트 double에서 128 비트 decimal또는 300 자 이상의 형식 문자열로 캐스팅하는 더 빠른 성능 테스트를 수행하지 않았습니다 . 아, 그리고 변환 중에 오버플로 오류가 발생할 수 있지만 값이 적합하면 decimal제대로 작동합니다.

업데이트 : 캐스팅이 훨씬 빨라진 것 같습니다. 다른 답변과 같이 준비된 형식 문자열을 사용하면 백만 번 형식을 지정하는 데 2.3 초가 걸리고 0.19 초만 전송됩니다. 반복 가능. 그건 10 배 빨라진 . 이제는 값 범위에 관한 것입니다.


이것은 불행히도 매우 크거나 작은 숫자의 지정된 사양에는 작동하지 않습니다. ((decimal)(1e-200)).ToString()예를 들어 0잘못된 반환 .
Lucero

1
공정하고 사과와 사과를 비교하려면이 방법을 double.ToString("0.############################"). 내 테스트에 따르면 당신은 3 배 더 빠릅니다. 어느 쪽이든 아래에 숫자를 인쇄 할 필요 1e-28가없고 double이 크지 않다는 것을 확실히 알고있는 경우에만 유효한 대답 이며, 둘 다 원래 질문의 제약 조건이 아닙니다.
jnm2

2
이것은 꽤 좋은 솔루션을 사용하면 값 범위를 알고 주어진입니다
아르투르 Udod을

8

이것은 내가 지금까지 얻은 것이며 작동하는 것처럼 보이지만 누군가가 더 나은 해결책을 가지고있을 수 있습니다.

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은 다음 학업에 대한 해결책을 제공하지 않기 때문에 (그리고 불가능합니다) : double d1 = 1e-200; d = d + 1; ToFloatingPointString (d)는 여기서 1을 반환합니다. 1,000이 아닙니다 ........... 000001.
JCasso 2009

5
아주 작은 더블에 하나를 추가하는 것은 당신의 생각 일 뿐이며 당면한 질문과는 아무 관련이 없습니다. d = d + 1없이 실행하면 실제로 0.000 ..... 0001이 표시되는 것을 볼 수 있습니다.
Lucero

"상수"값을 설정하는 대신 런타임에 1e-200을 계산하는 방법을 찾으면 투표하겠습니다.
JCasso 2009

2
문제 없어요. double x = 1.0; for (int i = 0; i < 200; i++) x /= 10; Console.WriteLine(x);
Lucero

6
실제로는 15 자리 숫자 만 의미가 있기 때문입니다.하지만 지수를 사용하여 매우 크거나 아주 작게 "이동"할 수 있습니다. 그러나 약 15 자리 이상의 숫자로 아주 작은 숫자를 추가 할 수는 없습니다. 그렇게하는 것은 유효 숫자의 수를 초과하고 큰 숫자가 더 중요하기 때문에 작은 부분이 손실되기 때문입니다. 따라서 유사한 범위의 숫자 (예 : 1e-200 및 1e-200 또는 1 + 1 또는 1e200 + 1e200 추가)로 계산하면 작동하지만 이러한 값을 혼합하면 더 작은 값을 반올림합니다.
Lucero

4

#.###...###or를 사용하는 문제 F99는 끝 소수점 자리에서 정밀도를 유지하지 않는다는 것입니다. 예 :

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

문제 DecimalConverter.cs는 느리다는 것입니다. 이 코드는 Sasik의 답변과 동일한 아이디어이지만 두 배 빠릅니다. 하단의 단위 테스트 방법.

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

필수 로그 기반 솔루션입니다. 이 솔루션은 수학을 포함하므로 숫자의 정확도를 약간 떨어 뜨릴 수 있습니다. 심하게 테스트되지 않았습니다.

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

편집 : 소수점이 숫자의 0이 아닌 부분을 교차하면이 알고리즘은 비참하게 실패합니다. 나는 단순한 것을 시도했고 너무 멀리 갔다.


입력 해 주셔서 감사합니다. 이와 같이 완벽하게 작동하는 솔루션을 구현하고이를 저와 비교해 보겠습니다.
Lucero

3

우리가 직접 포맷터를 작성해야했던 옛날에는 가수와 지수를 분리하여 따로 포맷했습니다.

Jon Skeet ( https://csharpindepth.com/articles/FloatingPoint ) 의이 기사에서 그는 원하는 작업을 정확히 수행해야하는 DoubleConverter.cs 루틴에 대한 링크를 제공합니다. Skeet은 또한 c #의 double에서 가수와 지수를 추출 할 때 이것을 참조합니다 .


링크 주셔서 감사합니다. 저는 이미 Jon의 코드를 시도해 보았지만 제 목적 상 너무 정확합니다. 예를 들어 0.1은 0.1로 표시되지 않습니다 (기술적으로 정확하지만 필요한 것은 아님) ...
Lucero

그래,하지만 알다시피 Jon의 코드의 요점은 숫자를 정확히 표시하는 것이며 이것은 내 경우에 너무 많은 것입니다. ToString ()을 수행 할 때 런타임에 의해 수행되는 반올림은 나에게 적합하며 여기에서 제안 된 대부분의 솔루션이 추가 처리를 위해 ToString ()을 기본으로 사용하는 이유이기도합니다.
Lucero

여보세요! 저는 10 년 후부터 Jon의 기사에 대한 하이퍼 링크가 끊어 졌음을 알려 드리기 위해 여기에 왔습니다.
Nick Vaccaro

2

음의 지수 값에 대해 작동하도록 위의 코드를 즉석에서 수정했습니다.

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

이 코드는 입력 디렉터리를 사용하고 구분 기호를 기반으로 과학적 표기법의 모든 값을 숫자 형식으로 변환합니다.

감사


1

이걸로 해봐:

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

전 세계적으로 수백만 명의 프로그래머이기 때문에 누군가가 이미 문제에 부딪혔다면 검색을 시도하는 것이 항상 좋은 습관입니다. 때로는 해결책이 쓰레기입니다. 즉, 직접 작성할 때가되었고, 때로는 다음과 같은 훌륭한 것이 있습니다.

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

(세부 정보 : http://www.yoda.arachsys.com/csharp/floatingpoint.html )


1
)이 이미 ebpower에 의해 게시 된 ... 거기에 코멘트를 볼 동일합니다
루세

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

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

이 코드의 기능과 다른 15 개 정도의 답변과 다른 점을 간단히 설명해 주시겠습니까?
JJJ

Stack Overflow에 오신 것을 환영합니다! 이 코드 스 니펫은 질문을 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 큰 도움이됩니다. 미래에 독자를 위해 질문에 답하고 있으며 해당 사용자는 코드 제안 이유를 모를 수 있습니다. 또한 설명 주석으로 코드를 복잡하게 만들지 마십시오. 이렇게하면 코드와 설명의 가독성이 감소합니다!
kayess

-1

내가 틀릴 수도 있지만, 그렇지 않나요?

data.ToString("n");

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


당신의 대답을 보았을 때 나는 당신의 질문을 오해했을 것입니다.
csharptest.net

아니요, 먼저 천 단위 구분 기호를 원하지 않고 두 번째 쉼표 뒤에는 항상 고정 된 자릿수가있는 것 같습니다. N 형식에 대한 MSDN 도움말도 참조하십시오. msdn.microsoft.com/en-us/library/dwhawy9k.aspx#NFormatString
Lucero

소수점 자리 뒤에 더 추가 할 수도 있습니다 (예 : "n8"또는 "n50"등).
BrainSlugs83 2013

-1

jcasso가 말한 것을 바탕으로 지수를 변경하여 이중 값을 조정하여 좋아하는 형식이 자동으로 수행되도록 형식을 적용하고 결과를 0으로 채우는 것보다 조정을 보완하는 것입니다.


IEEE 부동 소수점 숫자의 지수는 2 진수이지만 10 진수는 10 진수입니다. 따라서 이것은 작동하지 않습니다. 이것은 0.1을 double에 정확한 값으로 저장할 수없는 이유이기도합니다. 또는 내가 귀하의 답변을 오해했다고 생각되면 샘플 (코드)을 제공하십시오.
Lucero

-1

IFormat 만 사용하면된다고 생각합니다.

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

예:

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

6
컴파일도 안 돼요, 컴파일하는 글을 올릴 수 있나요?
Lucero

-1

내 솔루션은 사용자 지정 형식을 사용하고있었습니다. 이 시도:

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

2
위에서 지정한 테스트 번호로 시도해보십시오. d = 1.5E200d = 1E-200. 결과 문자열은 거의 200 0자 여야 합니다. 그렇지 않으면 솔루션이 작동하지 않습니다.
Lucero

소수점 이하 9 자리는 범용 솔루션에 충분하지 않습니다. doubleValue.ToString("0." + new string('#', 339))무손실입니다. 값을 사용하여 이러한 방법을 비교하십시오 double.Epsilon.
jnm2

-1

이것은 나를 위해 잘 작동합니다 ...

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

//Output: "150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

1
예, 큰 숫자에 대해서는 작동하지만 쉼표 뒤에있는 것은 작동하지 않습니다 1.5e-200. 특히 .
Lucero
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.