"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > जावास्क्रिप्ट में वित्तीय परिशुद्धता: एक सेंट भी गँवाए बिना पैसा संभालें

जावास्क्रिप्ट में वित्तीय परिशुद्धता: एक सेंट भी गँवाए बिना पैसा संभालें

2024-08-30 को प्रकाशित
ब्राउज़ करें:170

Financial Precision in JavaScript: Handle Money Without Losing a Cent

वित्त की तेज़ गति वाली दुनिया में, सटीकता ही सब कुछ है। राउंडिंग/परिशुद्धता त्रुटि के कारण लाखों डॉलर के नुकसान से बचना हमेशा बेहतर होता है।

जब पैसे की बात आती है, तो डेटाटाइप के बारे में सोचें

इस लेख का शुरुआती बिंदु यह अहसास है कि पैसा आपकी औसत मूल संख्या नहीं है जिसका उपयोग आप अपनी टोकरी में सेब गिनने के लिए कर सकते हैं। जब आप 10€ को 10$ से गुणा करने का प्रयास करते हैं तो आपको क्या मिलता है? कठिन हुह... क्या आपको कभी किसी पुराने जैकेट की जेब में चमत्कारी $1.546 मिला है? हाँ, मैं जानता हूँ, यह वास्तव में संभव भी नहीं है। ये मूर्खतापूर्ण उदाहरण इस तथ्य को स्पष्ट करने के लिए यहां हैं कि पैसे के अपने विशेष नियम हैं और इसे केवल एक साधारण संख्या के आधार पर नहीं बनाया जा सकता है। मैं आपको आश्वस्त करता हूं, मैं पहला व्यक्ति नहीं हूं जिसे इसका एहसास हुआ (और हो सकता है कि आपको मुझसे पहले ही इसका एहसास हो गया हो)। 2002 में, प्रोग्रामर मार्टिन फाउलर ने एंटरप्राइज एप्लिकेशन आर्किटेक्चर के पैटर्न में विशिष्ट विशेषताओं और ऑपरेंड नियमों के साथ पैसे का प्रतिनिधित्व करने का एक तरीका प्रस्तावित किया। उनके लिए, धन डेटाटाइप के लिए आवश्यक दो न्यूनतम व्यवहार्य विशेषताएँ थीं:

amount
currency

यह वास्तव में बुनियादी प्रतिनिधित्व एक सरल लेकिन मजबूत मौद्रिक मॉडल के निर्माण के लिए हमारा शुरुआती बिंदु होगा।

धन राशियाँ, उनका प्रतिनिधित्व कैसे करें

एक धन राशि निश्चित रूप से एक विशेष संख्या है: इसकी एक निश्चित सटीकता होती है (फिर से, आपकी जेब में 4.376$ नहीं हो सकते)। आपको इसका प्रतिनिधित्व करने का एक तरीका चुनना होगा जो आपको इस बाधा का सम्मान करने में मदद करे।

एक भोला दृष्टिकोण, मूल संख्या जावास्क्रिप्ट डेटाटाइप

स्पॉयलर अलर्ट, यह निश्चित रूप से एक अच्छा विचार नहीं है यदि आप फ्लोटिंग-पॉइंट संख्या प्रतिनिधित्व की अंधेरी दुनिया में कुछ सेंट (यदि यह डॉलर नहीं है) को गायब होते नहीं देखना चाहते हैं।

महँगी परिशुद्धता त्रुटि

यदि आपके पास जावास्क्रिप्ट में कोडिंग का कुछ अनुभव है, तो आप जानते हैं कि सबसे सरल गणना के परिणामस्वरूप भी सटीक त्रुटि हो सकती है जिसकी आपको पहले उम्मीद नहीं होगी। इस घटना को उजागर करने वाला सबसे स्पष्ट और प्रसिद्ध उदाहरण है:

0.1   0.2 !== 0.3 // true
0.1   0.2 // 0.30000000000000004

यदि यह उदाहरण आपको पूरी तरह से आश्वस्त नहीं करता है, तो मैं आपको सलाह देता हूं कि आप इस लेख पर एक नजर डालें, जो उन सभी समस्याग्रस्त गणना परिणामों के बारे में थोड़ा और विस्तार से बताता है जिनका सामना आप जावास्क्रिप्ट मूल संख्या प्रकार के साथ काम करते समय कर सकते हैं...

परिणामों में यह मामूली डेल्टा आपके लिए हानिरहित प्रतीत हो सकता है (लगभग ~ 10^-16 की परिमाण के साथ), हालांकि एक महत्वपूर्ण वित्तीय अनुप्रयोग में, ऐसी त्रुटि तेजी से बढ़ सकती है। हजारों खातों के बीच धनराशि स्थानांतरित करने पर विचार करें, जहां प्रत्येक लेनदेन में समान गणना शामिल होती है। थोड़ी-सी अशुद्धियाँ बढ़ती जाती हैं, और इससे पहले कि आपको इसका पता चले, आपके वित्तीय विवरणों में हजारों डॉलर का नुकसान हो जाता है। और ईमानदारी से, हम सभी इस बात से सहमत हो सकते हैं कि जब पैसे की बात आती है, तो गलती की अनुमति नहीं है: कानूनी रूप से भी और अपने ग्राहकों के साथ भरोसेमंद संबंध बनाने के लिए भी।

ऐसी त्रुटि क्यों?

अपने किसी प्रोजेक्ट में समस्या का सामना करते समय मैंने खुद से जो पहला सवाल पूछा वह है क्यों ? मैंने पाया कि समस्या का स्रोत जावास्क्रिप्ट नहीं है और ये अशुद्धियाँ अन्य आधुनिक प्रोग्रामिंग भाषाओं (जावा, सी, पायथन…) को भी प्रभावित करती हैं।

// In C
#include 

int main() {
    double a = 0.1;
    double b = 0.2;
    double sum = a   b;
    if (sum == 0.3) {
        printf("Equal\n");
    } else {
        printf("Not Equal\n"); // This block is executed
    }
    return 0;
}

// > Not equal
// In Java
public class doublePrecision {
    public static void main(String[] args) {

        double total = 0;
        total  = 5.6;
        total  = 5.8;
        System.out.println(total);
    }
}

// > 11.399999999999

वास्तव में, मूल कारण इन भाषाओं द्वारा फ़्लोटिंग-पॉइंट संख्याओं का प्रतिनिधित्व करने के लिए उपयोग किए जाने वाले मानक में निहित है: आईईईई 754 मानक द्वारा निर्दिष्ट डबल (या एकल)-सटीक फ़्लोटिंग-पॉइंट प्रारूप।

आईईईई 754 मानक: बिट प्रतिनिधित्व की एक कहानी

जावास्क्रिप्ट में, मूल प्रकार की संख्या डबल-सटीक फ़्लोटिंग-पॉइंट संख्याओं से मेल खाती है, जिसका अर्थ है कि एक संख्या 64 बिट्स के साथ एन्कोड की गई है और तीन भागों में विभाजित है:

  • चिह्न के लिए 1 बिट
  • प्रतिपादक के लिए 11 बिट्स
  • मैन्टिसा (या अंश) के लिए 52 बिट्स जो 0 से 1 तक होते हैं

Financial Precision in JavaScript: Handle Money Without Losing a Cent

Financial Precision in JavaScript: Handle Money Without Losing a Cent

फिर, आपको अपने बिट प्रतिनिधित्व को दशमलव मान में बदलने के लिए निम्नलिखित सूत्र का उपयोग करने की आवश्यकता है:

Financial Precision in JavaScript: Handle Money Without Losing a Cent

डबल-प्रिसिजन फ़्लोटिंग-पॉइंट संख्या प्रतिनिधित्व का एक उदाहरण, 1/3 का अनुमान:

0 01111111101 0101010101010101010101010101010101010101010101010101

= (-1)^0 x (1   2^-2   2^-4   2^-6   ...   2^-50   2^-52) x 2^(1021-1023)
= 0.333333333333333314829616256247390992939472198486328125
~ 1/3

यह प्रारूप हमें मूल्यों की एक विस्तृत श्रृंखला का प्रतिनिधित्व करने की अनुमति देता है, लेकिन यह पूर्ण सटीकता के साथ हर संभव संख्या का प्रतिनिधित्व नहीं कर सकता है (केवल 0 और 1 के बीच आप संख्याओं की अनंत संख्या पा सकते हैं...)। कई संख्याओं को बाइनरी रूप में सटीक रूप से प्रदर्शित नहीं किया जा सकता है। पहले उदाहरण पर लूप करने के लिए, 0.1 और 0.2 के साथ यही समस्या है। डबल-पॉइंट फ़्लोटिंग प्रतिनिधित्व हमें इन मानों का अनुमान देता है, इसलिए जब आप इन दो अस्पष्ट प्रतिनिधित्वों को जोड़ते हैं, तो परिणाम भी सटीक नहीं होता है।

एक संभावित समाधान: मनमाना दशमलव अंकगणित

अब जब आप पूरी तरह से आश्वस्त हो गए हैं कि मूल जावास्क्रिप्ट नंबर प्रकार के साथ धन राशि को संभालना एक बुरा विचार है (कम से कम मुझे आशा है कि आपको इसके बारे में संदेह होना शुरू हो जाएगा), 1 अरब डॉलर का सवाल यह है कि आपको कैसे आगे बढ़ना चाहिए ? इसका समाधान जावास्क्रिप्ट में उपलब्ध कुछ शक्तिशाली निश्चित-सटीक अंकगणितीय पैकेजों का उपयोग करना हो सकता है। उदाहरण के लिए Decimal.js (जिसका उपयोग लोकप्रिय ORM प्रिज्मा द्वारा अपने दशमलव डेटाटाइप को दर्शाने के लिए किया जाता है) या Big.js.

ये पैकेज आपको विशेष डेटाटाइप प्रदान करते हैं जो आपको ऊपर बताई गई सटीक त्रुटियों से छुटकारा पाने के साथ गणना करने की अनुमति देते हैं।

// Example using Decimal.js
const Decimal = require('decimal.js');
const a = new Decimal('0.1');
const b = new Decimal('0.2');
const result = a.plus(b);

console.log(result.toString()); // Output: '0.3'

यह दृष्टिकोण आपको एक और लाभ प्रदान करता है, यह प्रतिनिधित्व किए जा सकने वाले अधिकतम मूल्य को काफी हद तक बढ़ाता है, जो उदाहरण के लिए क्रिप्टोकरेंसी के साथ काम करते समय काफी उपयोगी हो सकता है।
भले ही यह वास्तव में मजबूत हो, लेकिन यह वह नहीं है जिसे मैं अपने वेब अनुप्रयोगों में लागू करना पसंद करता हूं। मुझे केवल पूर्णांक मानों से निपटने के लिए Stripe रणनीति लागू करना आसान और स्पष्ट लगता है।

मास्टर्स से सीखें: स्ट्राइप, एक नो-फ़्लोटिंग पॉइंट रणनीति

हम, थियोडो फिनटेक में, व्यावहारिकता को महत्व देते हैं! हम उद्योग की सबसे सफल कंपनियों से प्रेरणा लेना पसंद करते हैं। भुगतान सेवाओं में विशेषज्ञता वाली प्रसिद्ध अरबों डॉलर की कंपनी स्ट्राइप ने फ्लोटिंग नंबरों के बिना बल्कि पूर्णांक के साथ धन राशि को संभालने का विकल्प चुना। ऐसा करने के लिए, वे मौद्रिक राशि का प्रतिनिधित्व करने के लिए मुद्रा की सबसे छोटी इकाई का उपयोग करते हैं।

// 10 USD are represented by
{
 "amount": 1000,
 "currency": "USD"
}

मुद्रा न्यूनतम इकाइयाँ... सुसंगत नहीं हैं!

मुझे लगता है कि आप में से कई लोग यह पहले से ही जानते हैं: सभी मुद्राओं में समान परिमाण की सबसे छोटी इकाई नहीं होती है। उनमें से अधिकांश "दो-दशमलव" मुद्राएं (EUR, USD, GBP) हैं जिसका अर्थ है कि उनकी सबसे छोटी इकाई मुद्रा का 1/100वां हिस्सा है। हालाँकि, कुछ "तीन-दशमलव" मुद्राएँ (KWD) या यहाँ तक कि "शून्य-दशमलव" मुद्राएँ (JPY) भी हैं। (आप ISO4217 मानक का पालन करके इसके बारे में अधिक जानकारी प्राप्त कर सकते हैं)। इन असमानताओं को संभालने के लिए, आपको सबसे छोटी इकाई में दर्शाई गई राशि को संबंधित मुद्रा में परिवर्तित करने के लिए गुणक कारक को अपने धन डेटा प्रतिनिधित्व में एकीकृत करना चाहिए।

Financial Precision in JavaScript: Handle Money Without Losing a Cent

मैंने धन राशि को दर्शाने का एक तरीका चुना... ठीक है, लेकिन अब, मैं उन्हें कैसे पूर्णांकित करूं?

मुझे लगता है कि आपने पहले ही इसका पता लगा लिया है, आप या तो मूल संख्या, तीसरे पक्ष के मनमाने-सटीक पैकेज या पूर्णांक के साथ काम कर सकते हैं, गणना आपको फ़्लोटिंग-पॉइंट परिणामों तक ले जा सकती है (और करेगी) जिन्हें आपको अपने मौद्रिक के लिए गोल करने की आवश्यकता होगी परिमित परिशुद्धता. एक त्वरित उदाहरण के रूप में कभी भी बहुत अधिक नहीं होता है, मान लें कि आप पूर्णांक मानों को संभालते हैं और 8.5413% (आउच…) की वास्तव में सटीक ब्याज दर के साथ 16k$ का ऋण अनुबंधित करते हैं। फिर आपको 16k$ और अतिरिक्त राशि वापस करनी होगी

1600000 * 0.085413 // amount in cents
//Output in cents: 136660.8

मुख्य बात यह है कि गणना के बाद धन राशि की पूर्णांकीकरण प्रक्रिया को ठीक से संभालना है। अधिकांश समय, आपको तीन अलग-अलग प्रकार की राउंडिंग के बीच चयन करना पड़ता है:

  • क्लासिक राउंडिंग: निकटतम मान तक राउंड करें और यदि दो मानों के बीच आधा है, तो राउंड अप करें
  • बैंकर राउंडिंग: निकटतम मान तक राउंड करें और यदि दो मानों के बीच आधा हो, तो राउंड डाउन करें, यदि संख्या सम है, और यदि संख्या विषम है तो राउंड अप करें (यह आपको संख्यात्मक स्थिरता देता है जब आपको बहुत सारे प्रदर्शन करने होते हैं) गोलाई)
  • कस्टम राउंडिंग: आपके द्वारा उपयोग की जाने वाली मुद्रा और आपके द्वारा संभाले जा रहे उपयोग के मामले के लिए विशेष कानून पर आधारित
जब राउंडिंग की बात आती है, तो वास्तव में कोई

"जादुई चटनी" नहीं होती है: आपको अपनी स्थिति के आधार पर मध्यस्थता करने की आवश्यकता होती है। मेरा सुझाव है कि जब आप नई मुद्रा और नए राउंडिंग उपयोग के मामले (रूपांतरण, धन विभाजन, क्रेडिट के लिए ब्याज दरें…) से निपटते हैं तो हमेशा कानून की जांच करें। आगे की परेशानियों से बचने के लिए बेहतर होगा कि आप तुरंत नियमों का पालन करें। उदाहरण के लिए, जब रूपांतरण दरों की बात आती है, तो अधिकांश मुद्राओं ने आवश्यक परिशुद्धता और पूर्णांकन नियमों के बारे में नियम निर्धारित किए हैं (आप यहां EUR रूपांतरण दर नियमों पर एक नज़र डाल सकते हैं)।

निष्कर्ष

यह लेख जावास्क्रिप्ट में धन राशि को संभालने की सभी मौजूदा संभावनाओं के बारे में संपूर्ण नहीं है और इसका उद्देश्य आपको पूर्ण/संपूर्ण धन डेटा मॉडल देना भी नहीं है। मैंने आपको एक ऐसे प्रतिनिधित्व को लागू करने के लिए पर्याप्त संकेत और दिशानिर्देश देने की कोशिश की जो सुसंगत, लचीला साबित हुआ और जिसे फिनटेक उद्योग के बड़े अभिनेताओं द्वारा चुना गया था। मुझे आशा है कि आप अपनी भविष्य की परियोजनाओं में धन राशि की गणना अपनी जेब में कुछ भी भूले बिना करने में सक्षम होंगे (अन्यथा अपनी पुरानी जैकेट पर नज़र डालना न भूलें)!

विज्ञप्ति वक्तव्य इस लेख को इस पर पुनर्मुद्रित किया गया है: https://dev.to/benjamin_renoux/financial-precision-in-javascript-handle-thorteout-lithout-a-cent-1chc?1 यदि कोई उल्लंघन है, तो कृपया इसे हटाने के लिए [email protected] पर संपर्क करें।
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3