Featured image of post कंप्यूटर 0.1 + 0.2 की सही गणना क्यों नहीं कर पाते? फ्लोटिंग-पॉइंट और राउंडिंग एरर का विज्ञान

कंप्यूटर 0.1 + 0.2 की सही गणना क्यों नहीं कर पाते? फ्लोटिंग-पॉइंट और राउंडिंग एरर का विज्ञान

प्रस्तावना: ‘0.1 + 0.2’ की रहस्यमयी पहेली

प्रत्येक प्रोग्रामर ने अपने जीवन में कभी न कभी इस परिणाम को देखकर आश्चर्य अवश्य महसूस किया होगा:

1
2
3
4
console.log(0.1 + 0.2);
// आउटपुट: 0.30000000000000004
console.log(0.1 + 0.2 === 0.3);
// आउटपुट: false

अरबों-खरबों गणनाएं प्रति सेकंड करने वाले आधुनिक सुपरकंप्यूटर $0.1 + 0.2 = 0.3$ जैसे प्राथमिक स्तर के जोड़ में क्यों अटक जाते हैं? यह किसी प्रोग्रामिंग भाषा का बग नहीं है। स्मार्टफोन से लेकर दुनिया के सबसे शक्तिशाली सुपरकंप्यूटर तक, सभी डिजिटल सिस्टम सटीक रूप से यही आउटपुट देते हैं: 0.30000000000000004।

  flowchart TD
    subgraph Dec ["दशमलव जगत (मानव अंतर्ज्ञान)"]
        D1["0.1 = 1/10 (सांत दशमलव)"]
        D2["0.2 = 1/5 (सांत दशमलव)"]
        D3["0.1 + 0.2 = 0.3 (पूर्णतः समान)"]
        D1 --> D3
        D2 --> D3
    end

    subgraph Bin ["बाइनरी हार्डवेयर जगत (IEEE 754)"]
        B1["0.1 = (0.000110011...)₂\nअनंत आवर्ती भिन्न"]
        B2["0.2 = (0.001100110...)₂\nअनंत आवर्ती भिन्न"]
        B3["53 बिट पर कटाई और घातांक संरेखण\nनिकटतम सम संख्या पर राउंडिंग"]
        B4["अंतिम संचित मान:\n0.3000000000000000444..."]
        B1 --> B3
        B2 --> B3
        B3 --> B4
    end

    Dec -.->|डिजिटल रूपांतरण| Bin
    style Dec fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style Bin fill:#ffe6e6,stroke:#cc0000,stroke-width:2px

1. बाइनरी में दशमलव संख्याएं अनंत आवर्ती क्यों बन जाती हैं?

दशमलव प्रणाली में $\frac{1}{3} = 0.3333\dots$ कभी समाप्त नहीं होता। संख्या सिद्धांत के अनुसार, कोई भिन्न $\frac{P}{Q}$ आधार $N$ में सांत दशमलव तभी बन सकती है जब हर $Q$ के सभी अभाज्य गुणनखंड आधार $N$ के अभाज्य गुणनखंड हों।

  • 10 आधार ($10 = 2 \times 5$) में 2 और 5 गुणनखंड वाली भिन्नें सांत होती हैं ($0.1 = \frac{1}{10}$)।
  • 2 आधार (बाइनरी) में केवल 2 ही अभाज्य गुणनखंड है। केवल वही भिन्नें सांत होंगी जिनके हर में $2^k$ हो।
$$(0.1)_{10} = (0.0001100110011\dots)_2$$

मेमोरी सीमित होने के कारण कंप्यूटर को इसे काटना पड़ता है, जिससे सूक्ष्म त्रुटि उत्पन्न होती है।


2. IEEE 754 मानक और आंतरिक जोड़ प्रक्रिया

IEEE 754 (binary64) के तहत 64 बिट्स इस प्रकार विभाजित होते हैं:

  • 1 साइन बिट
  • 11 एक्सपोनेंट बिट्स (1023 बायस के साथ)
  • 52 मैंटीसा बिट्स (निहित बिट के साथ 53 बिट्स की प्रभावी सटीकता)।
$$\mathbf{0.300000000000000044408920985...}$$

इसीलिए 0.1 + 0.2 === 0.3 का मान false आता है।


3. ऐतिहासिक त्रासदियां और समाधान

  • पैट्रियट मिसाइल विफलता (1991): 0.1 सेकंड की समय त्रुटि 100 घंटे लगातार चलने से 0.34 सेकंड का विचलन बन गई, जिससे राडार स्कड मिसाइल को 687 मीटर से चूक गया और 28 सैनिकों की मृत्यु हुई।
  • एरियन 5 रॉकेट विस्फोट (1996): 64-बिट फ्लोट को 16-बिट इंटीजर में बदलने से ओवरफ्लो हुआ और 500 मिलियन डॉलर का रॉकेट नष्ट हो गया।

इंजीनियरिंग नियम:

  1. कभी भी फ्लोटिंग-पॉइंट मानों की सीधे समानता (==) से तुलना न करें; एप्सिलॉन टॉलरेंस (math.isclose) का प्रयोग करें।
  2. वित्तीय प्रणालियों में कभी फ्लोट का प्रयोग न करें; पैसे को इंटीजर (पैसा/सेंट) या Decimal लाइब्रेरी में रखें।

5. अतिरिक्त ऐतिहासिक उदाहरण: पेंटियम बग और वैंकूवर स्टॉक एक्सचेंज

सैन्य और अंतरिक्ष दुर्घटनाओं के अतिरिक्त, कंप्यूटर विज्ञान के इतिहास में ऐसी वित्तीय और तकनीकी घटनाएं भी दर्ज हैं जहां फ्लोटिंग-पॉइंट की उपेक्षा से भारी नुकसान हुआ।

5.1 वैंकूवर स्टॉक एक्सचेंज इंडेक्स का रहस्यमयी पतन (1982)

1982 में वैंकूवर स्टॉक एक्सचेंज ने एक नया बाजार सूचकांक तैयार किया जिसका आरंभिक मूल्य 1000.000 रखा गया। प्रत्येक सौदे के बाद सूचकांक को पुनर्गणित किया जाता था। परंतु सॉफ्टवेयर प्रोग्रामर ने एक भूल की: सही राउंडिंग करने के स्थान पर उन्होंने मान को तीसरे दशमलव स्थान पर काट (truncate) दिया। प्रत्येक लेन-देन में थोड़े से धनात्मक अंश को काट देने से एक संचयी ऋणात्मक पूर्वाग्रह पैदा हो गया। 22 महीनों के भीतर, जबकि वास्तविक बाजार बढ़ रहा था, सूचकांक गिरकर 520 अंक पर आ गया! जब गणितज्ञों ने कोड को सुधारा और उचित राउंडिंग लागू की, तो सूचकांक तुरंत छलांग लगाकर 1098 अंक से ऊपर पहुंच गया।

5.2 इंटेल पेंटियम का प्रसिद्ध FDIV डिवीजन बग (1994)

$$\frac{4195835}{3145727}$$

का परिणाम पांचवें दशमलव स्थान पर गलत आता था। इसका कारण सिलिकॉन चिप पर बनी SRT डिवीजन एल्गोरिदम तालिका में 2048 में से 5 प्रविष्टियों का छूट जाना था। इस गलती के कारण इंटेल को दुनिया भर से लाखों प्रोसेसर बदलने पड़े और 475 मिलियन डॉलर का नुकसान हुआ।


6. काहान समेशन एल्गोरिदम: संचयी त्रुटि का गणितीय समाधान

करोड़ों संख्याओं को जोड़ते समय छोटी संख्याओं को बड़े मानों में विलीन होने (Absorption) से बचाने के लिए ट्यूरिंग पुरस्कार विजेता विलियम काहान ने यह सुधारात्मक एल्गोरिदम बनाया:

1
2
3
4
5
6
7
8
9
def kahan_sum(data):
    total = 0.0
    c = 0.0  # खोई हुई त्रुटि को संचित करने वाला चर
    for x in data:
        y = x - c
        t = total + y
        c = (t - total) - y  # छूटे हुए बिट्स की भरपाई
        total = t
    return total

इस विधि से करोड़ों डेटा बिंदुओं के योग में भी राउंडिंग एरर नगण्य बना रहता है।

comments powered by Disqus