वैज्ञानिक संकेतन के बिना डबल स्ट्रिंग में रूपांतरण


81

.NET फ्रेमवर्क में वैज्ञानिक अंकन के बिना एक डबल को फ्लोटिंग-पॉइंट स्ट्रिंग प्रतिनिधित्व में कैसे परिवर्तित किया जाए?

"छोटे" नमूने (प्रभावी संख्या किसी भी आकार के हो सकते हैं, जैसे 1.5E200या 1e-200):

3248971234698200000000000000000000000000000000
0.00000000000000000000000000000000000023897356978234562

में से कोई भी मानक संख्या स्वरूप इस तरह कर रहे हैं, और एक कस्टम प्रारूप भी दशमलव विभाजक के बाद अंक का एक खुला संख्या होने की अनुमति देने के प्रतीत नहीं होता।

यह 10 प्रतिनिधित्व (ई -05) के लिए शक्ति के बिना डबल स्ट्रिंग को परिवर्तित करने का एक डुप्लिकेट नहीं है क्योंकि वहां दिए गए उत्तर हाथ में समस्या को हल नहीं करते हैं । इस प्रश्न में स्वीकृत समाधान एक निश्चित बिंदु (जैसे 20 अंक) का उपयोग करना था, जो कि मैं नहीं चाहता। एक निश्चित बिंदु स्वरूपण और बेमानी ट्रिमिंग 0 इस समस्या को हल नहीं करता है क्योंकि निश्चित चौड़ाई के लिए अधिकतम चौड़ाई 99 वर्ण है।

नोट: समाधान को कस्टम संख्या स्वरूपों (जैसे अन्य दशमलव विभाजक, संस्कृति की जानकारी के आधार पर) के साथ सही ढंग से निपटना है।

संपादित करें: सवाल केवल उपरोक्त संख्याओं को विस्थापित करने के बारे में है। मुझे पता है कि फ्लोटिंग पॉइंट नंबर कैसे काम करते हैं और उनके साथ किन नंबरों का उपयोग और गणना की जा सकती है।


1
क्या अब आपके पास इस प्रश्न का हल है?
किरा

@ आनंद, दो समाधान हैं जो काम करते हैं (पॉल सासिक और मेरा) भले ही वे "अच्छा" (स्ट्रिंग हेरफेर के माध्यम से नहीं) जा रहे हैं।
लुसेरो

जवाबों:


41

सामान्य प्रयोजन के समाधान के लिए आपको 339 स्थानों को संरक्षित करने की आवश्यकता है:

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

गैर-शून्य दशमलव अंकों की अधिकतम संख्या 16 है। 15 दशमलव बिंदु के दाईं ओर हैं। प्रतिपादक उन 15 अंकों को अधिकतम 324 स्थानों पर स्थानांतरित कर सकता है। ( रेंज और परिशुद्धता देखें। )

यह के लिए काम करता है double.Epsilon, double.MinValue, double.MaxValue, और बीच में कुछ भी।

प्रदर्शन regex / string हेरफेर समाधानों की तुलना में बहुत अधिक होगा क्योंकि सभी प्रारूपण और स्ट्रिंग कार्य अप्रबंधित सीएलआर कोड द्वारा एक पास में किए जाते हैं। साथ ही, कोड सही साबित करने के लिए बहुत सरल है।

उपयोग में आसानी और बेहतर प्रदर्शन के लिए, इसे स्थिर बनाएं:

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

¹ अद्यतन: मैंने गलती से कहा कि यह भी एक दोषरहित समाधान था। वास्तव में, यह नहीं है, क्योंकि ToStringइसके सामान्य प्रारूप को छोड़कर सभी प्रारूपों के लिए गोलाई है rजीवंत उदाहरण। धन्यवाद, @Lathing! कृपया देखें Lothing का जवाब अगर आप निश्चित बिंदु संकेतन (यानी, आप उपयोग कर रहे हैं में गोल करने की क्षमता की जरूरत है .ToString("r")आज)।


अच्छा और बहुत छोटा है, लेकिन अगर आपको बहुत बड़े मूल्यों की आवश्यकता नहीं है, तो आप तेजी से 10x कर सकते हैं। मेरा जवाब देखें: stackoverflow.com/a/36204442/143684
ygoe

धन्यवाद, पूरी तरह से काम किया। आप एक अद्भुत इंसान हैं। Upvoted।
स्नूप

1
यह समाधान "शिथिल" नहीं है। उदाहरण: String t1 = (0.0001/7).ToString("0." + new string('#', 339)); // 0.0000142857142857143बनाम: String t2 = (0.0001/7).ToString("r"); // 1.4285714285714287E-05सटीक दशमलव स्थानों पर खो जाता है।
घृणा

30

मेरे पास एक समान समस्या थी और यह मेरे लिए काम कर रहा था:

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

F99 ओवरकिल हो सकता है, लेकिन आपको यह विचार मिलता है।


1
99 पर्याप्त नहीं है, और इसे कॉमा से पहले और पीछे दोनों के लिए काम करना है।
लुसारो

2
TrimEnd('0')पर्याप्त है, क्योंकि charसरणी है params। यही है, किसी भी chars पारित करने के TrimEndलिए स्वचालित रूप से एक सरणी में समूहीकृत किया जाएगा।
Grault

99 एक सामान्य-उद्देश्य समाधान के लिए पर्याप्त नहीं है। doubleValue.ToString("0." + new string('#', 339))दोषरहित है। मान का उपयोग करके इन विधियों की तुलना करें double.Epsilon
jnm2

20

यह एक स्ट्रिंग पार्सिंग समाधान है जहां स्रोत संख्या (डबल) को एक स्ट्रिंग में परिवर्तित किया जाता है और इसके घटक घटकों में पार्स किया जाता है। यह तो पूर्ण लंबाई के संख्यात्मक प्रतिनिधित्व में नियमों द्वारा आश्वस्त किया गया है। यह अनुरोध के अनुसार लोकेल के लिए भी खाता है।

अपडेट : रूपांतरणों के परीक्षणों में केवल एकल-अंक पूरे नंबर शामिल हैं, जो आदर्श है, लेकिन एल्गोरिथ्म भी कुछ के लिए काम करता है: 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 का उपयोग नहीं करने के लिए चुना और मैंने अपना स्ट्रिंग पार्स किया। क्या आपने इस समाधान का परीक्षण किया है? यह एक पूर्ण कंसोल ऐप है।
पॉल शशिक

अभी तक नहीं, जल्द ही करेंगे ...;)
ल्यूकोरो

3
यह एक और अधिक आसानी से पढ़ा जाता है, क्योंकि आपको रेगेक्स को नहीं करना है।
ग्रेगरी

+1 LOL @ "रेगेक्स को ग्रो करें" मुझे यह पसंद है। मैं इसे अपने विकास का हिस्सा बनाऊंगा! धन्यवाद।
पॉल शशिकला

खैर, रेगेक्स एक में कम से कम अच्छी तरह से नामित समूहों के बजाय कुछ सरणियों में असुरक्षित अनुक्रमित हैं ...;)
लुसिरो

13

आप डाली सकता है doubleकरने के लिए decimalऔर उसके बाद करना ToString()

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

मैंने प्रदर्शन परीक्षण नहीं किया है जो तेज है, 64-बिट doubleसे 128-बिट decimalया 300 से अधिक वर्णों के एक प्रारूप स्ट्रिंग के साथ कास्टिंग । ओह, और रूपांतरण के दौरान संभवतः अतिप्रवाह त्रुटियां हो सकती हैं, लेकिन यदि आपके मूल्य फिट हैं तो decimalयह ठीक काम करना चाहिए।

अद्यतन: लगता है कि कास्टिंग बहुत तेज़ है। अन्य प्रारूप में दिए गए तैयार प्रारूप स्ट्रिंग का उपयोग करते हुए, एक लाख बार प्रारूपण में 2.3 सेकंड लगते हैं और केवल 0.19 सेकंड कास्टिंग होते हैं। दोहराने योग्य। वह 10x तेज है । अब यह केवल मूल्य सीमा के बारे में है।


यह दुर्भाग्य से बहुत बड़ी या छोटी संख्या के दिए गए विनिर्देश के लिए काम नहीं करता है। ((decimal)(1e-200)).ToString()उदाहरण के लिए रिटर्न 0जो गलत है।
ल्यूकोरो

1
निष्पक्ष होना और सेब से सेब की तुलना करना, आपको इस विधि की तुलना करना चाहिए double.ToString("0.############################")। मेरे परीक्षण के अनुसार, तुम्हारा केवल 3x तेज है। किसी भी तरह से यह केवल एक वैध उत्तर है यदि आप यह सुनिश्चित करने के लिए जानते हैं कि आपको नीचे दिए गए अंकों को प्रिंट करने की आवश्यकता नहीं है 1e-28और यह कि आपका डबल बड़ा नहीं है, दोनों मूल प्रश्न में बाधा नहीं हैं।
jnm2

2
यह एक बहुत अच्छा समाधान है जिसे आप मान रेंज
Artur 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 के बाद से निम्न चरणों के लिए समाधान प्रदान नहीं करता है (और यह नहीं कर सकता): डबल d1 = 1e-200; d = d + 1; ToFloatingPointString (d) यहां केवल 1 रिटर्न देता है। 1,000 नहीं ........... 000001
जेकासो

5
बहुत छोटे डबल में से एक जोड़ना सिर्फ आपका विचार है, और हाथ में सवाल के साथ कुछ नहीं करना है। यदि आप इसे बिना d = d + 1 के चलाते हैं, तो आप देखेंगे कि यह वास्तव में 0.000 ..... 0001 प्रदर्शित करता है।
लुसेरो

"निरंतर" मान सेट करने के बजाय रनटाइम पर 1e-200 की गणना करने का तरीका ढूंढें, मैं इसे वोट करूंगा।
जेकासो

2
कोई दिक्कत नहीं है। double x = 1.0; for (int i = 0; i < 200; i++) x /= 10; Console.WriteLine(x);
ल्यूकोरो

6
ऐसा इसलिए है क्योंकि केवल 15 अंक वास्तव में सार्थक हैं, लेकिन आप उन्हें बहुत बड़े या बहुत छोटे होने के लिए घातांक के साथ "शिफ्ट" कर सकते हैं। लेकिन आप एक बहुत छोटी संख्या को एक संख्या के साथ नहीं जोड़ सकते हैं जो कि लगभग 15 अंकों से अधिक है, क्योंकि ऐसा करने से महत्वपूर्ण अंकों की संख्या अधिक हो जाती है और चूंकि बड़ी संख्या अधिक महत्वपूर्ण होती है, इसलिए छोटा भाग खो जाएगा। इसलिए, समान रेंज में संख्याओं के साथ गणना करना (जैसे 1e-200 और 1e-200, या 1 + 1, या 1e200 + 1e200 को जोड़ना) काम करता है, लेकिन ऐसे मूल्यों को मिलाने से छोटे मूल्य दूर हो जाएंगे।
लुकेरो

4

समस्या का उपयोग कर #.###...###या 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यह है कि यह धीमा है। यह कोड ससिक के उत्तर के समान है, लेकिन दो बार उपवास के रूप में है। इकाई परीक्षण विधि नीचे।

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

संपादित करें: यदि दशमलव बिंदु संख्या के गैर-शून्य भाग को पार कर जाता है, तो यह एल्गोरिथ्म बुरी तरह से विफल हो जाएगा। मैंने सरल के लिए कोशिश की और बहुत दूर चला गया।


इनपुट के लिए धन्यवाद, मैं इस तरह एक पूरी तरह से काम कर समाधान को लागू करने की कोशिश करूंगा और मेरी तुलना करूंगा।
ल्यूकोरो

3

पुराने दिनों में जब हमें अपने फॉर्मेट लिखने होते थे, हम मंटिसा और एक्सपोनेंट को अलग कर देते थे और उन्हें अलग-अलग प्रारूपित करते थे।

जॉन स्कीट ( https://csharpindepth.com/articles/FloatingPoint ) के इस लेख में वह अपने DoubleConverter.cs दिनचर्या का लिंक प्रदान करता है जो आपको वही करना चाहिए जो आप चाहते हैं। स्कीट भी इसे संदर्भित करता है पर mantissa निकालने और सी # में डबल से घातांक


लिंक के लिए धन्यवाद, मैंने पहले ही जॉन से कोड की कोशिश की है, हालांकि मेरे उद्देश्य के लिए यह बहुत सटीक है; उदाहरण के लिए, 0.1 0.1 के रूप में नहीं दिखता है (जो तकनीकी रूप से सही है, लेकिन मुझे जो चाहिए वह नहीं होगा ...
Lucero

हाँ, लेकिन आप देखते हैं, जॉन के कोड का पूरा बिंदु वास्तव में संख्या को प्रदर्शित करना है और यह मेरे मामले के लिए बहुत अधिक है। रनिंग द्वारा किया जाता है जब ToString () करना मेरे लिए ठीक है, और शायद यही कारण है कि यहां प्रस्तावित अधिकांश समाधान आगे की प्रक्रिया के लिए आधार के रूप में ToString () का उपयोग करते हैं।
ल्यूकोरो

नमस्कार! मैं भविष्य में 10 साल से यहां आया हूं आपको बता दें कि जॉन के लेख के हाइपरलिंक टूट गए हैं।
निक वैकेरो

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 द्वारा पोस्ट के रूप में ही है, वहाँ टिप्पणियों को देखें ...;)
Lucero

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

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

क्या आप संक्षेप में बता सकते हैं कि यह कोड क्या करता है और यह अन्य 15 या इतने उत्तरों से कैसे अलग है?
जेजे

ढेर अतिप्रवाह में आपका स्वागत है! हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और वे लोग आपके कोड सुझाव के कारणों को नहीं जान सकते हैं। कृपया व्याख्यात्मक टिप्पणियों के साथ अपने कोड को भीड़ने की कोशिश न करें, इससे कोड और स्पष्टीकरण दोनों की पठनीयता कम हो जाती है!
kayess

-1

मैं गलत हो सकता है, लेकिन क्या ऐसा नहीं है?

data.ToString("n");

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


आपके उत्तर को देखकर मुझे आपके प्रश्न पर खेद हुआ होगा, क्षमा करें।
csharptest.net

नहीं, पहले मुझे हजार विभाजक नहीं चाहिए और दूसरे को अल्पविराम के बाद हमेशा निश्चित संख्या में अंक मिलते हैं। यह भी देखें: एन प्रारूप के लिए MSDN मदद msdn.microsoft.com/en-us/library/dwhawy9k.aspx#NFormatString
Lucero

आप दशमलव स्थान (अर्थात "n8", या "n50", आदि) के बाद और भी जोड़ सकते हैं।
BrainSlugs83

-1

बस उस पर निर्माण करने के लिए जो jassasso ने कहा कि आप क्या कर सकते हैं घातांक को बदलकर अपने दोहरे मूल्य को समायोजित करें ताकि आपका पसंदीदा प्रारूप आपके लिए यह कर सके, प्रारूप लागू करें, और समायोजन के लिए क्षतिपूर्ति करने के लिए शून्य के साथ परिणाम पैड।


IEEE फ़्लोटिंग पॉइंट नंबरों में घातांक 2-बेस है, लेकिन दशमलव संख्या 10-बेस हैं। इसलिए, यह सिर्फ काम नहीं करता है। यही कारण है कि आप एक डबल में सटीक मान के रूप में 0.1 स्टोर नहीं कर सकते हैं। या कृपया बस कुछ नमूना (कोड) प्रदान करें यदि आपको लगता है कि मुझे आपका जवाब गलत लगा।
लुसिरो

-1

मुझे लगता है कि आपको केवल IFormat का उपयोग करने की आवश्यकता है

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

उदाहरण:

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

6
यह भी संकलित नहीं करता है, क्या आप कुछ संकलन कर सकते हैं?
ल्यूकोरो

-1

मेरा समाधान कस्टम प्रारूपों का उपयोग कर रहा था। इसे इस्तेमाल करे:

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

2
ऊपर दिए गए परीक्षण संख्याओं के साथ प्रयास करें: d = 1.5E200और d = 1E-200। परिणामस्वरूप स्ट्रिंग में लगभग 200 0वर्ण होने चाहिए, या आपका समाधान काम नहीं करता है।
लुसिरो

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
लुसेरो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.