इन-गेम मुद्रा के लिए मुझे किस डेटा-प्रकार का उपयोग करना चाहिए?


96

एक साधारण व्यापार सिमुलेशन गेम (जावा + स्लिक 2 डी में निर्मित) में, क्या किसी खिलाड़ी की वर्तमान राशि को एक floatया एक int, या कुछ और के रूप में संग्रहीत किया जाना चाहिए ?

मेरे उपयोग-मामले में, अधिकांश लेनदेन सेंट ($ 0.50, $ 1.20, आदि) का उपयोग करेंगे, और सरल ब्याज दर की गणना शामिल होगी।

मैंने लोगों को यह कहते हुए देखा है कि आपको कभी भी floatमुद्रा के लिए उपयोग नहीं करना चाहिए , साथ ही लोगों का कहना है कि आपको कभी भी intमुद्रा के लिए उपयोग नहीं करना चाहिए । मुझे लगता है कि मुझे intकिसी भी आवश्यक प्रतिशत गणना का उपयोग करना चाहिए और उसे गोल करना चाहिए । मुझे क्या उपयोग करना चाहिए?


2
इस सवाल पर StackOverflow पर चर्चा की गई। BigDecimal की तरह लगता है शायद जाने के लिए रास्ता है। stackoverflow.com/questions/285680/…
एड मिलर

2
क्या जावा में Currencyडेल्फी की तरह का एक प्रकार नहीं है , जो फ़्लोटिंग-पॉइंट पर अंतर्निहित सटीक समस्याओं के बिना आपको दशमलव गणित देने के लिए स्केल्ड-पॉइंट-पॉइंट गणित का उपयोग करता है?
मेसन व्हीलर

1
यह खेल है। लेखांकन आपको एक गोल बंद पेनी के लिए लिंच नहीं करने वाला है और इस प्रकार मुद्रा के लिए फ्लोटिंग पॉइंट का उपयोग करने के खिलाफ सामान्य कारण मायने नहीं रखते हैं।
लोरेन Pechtel

@MasonWheeler: जावा में BigDecimalइस तरह की समस्याएं हैं।
मार्टिन श्रोडर

जवाबों:


92

आप intसेंट में सब कुछ का उपयोग और विचार कर सकते हैं । $ 1.20 सिर्फ 120 सेंट है। प्रदर्शन पर, आप दशमलव को उस स्थान पर रखते हैं जहाँ यह है।

ब्याज की गणना बस छंटनी या गोल हो जाएगी। इसलिए

newAmt = round( 120 cents * 1.04 ) = round( 124.8 ) = 125 cents

इस तरह आपके पास गन्दा डेसीमल हमेशा नहीं रहता है। आप अपने स्वयं के बैंक खाते में पैसों के लिए बेहिसाब धन जमा कर सकते हैं


3
यदि आप उपयोग करते हैं roundतो नीचे उतरने का कोई वास्तविक कारण नहीं intहै?
सैम होसेवर

19
+1। फ़्लोटिंग पॉइंट नंबर्स समानता तुलनाओं को पेंच करते हैं, वे ठीक से प्रारूपित करना कठिन होते हैं, और समय के साथ अजीब गोलाई त्रुटियों को पेश करते हैं। यह सब कुछ अपने आप करना बेहतर है ताकि आपको बाद में इसके बारे में शिकायत न मिले। यह वास्तव में बहुत काम नहीं है।
डोबेस वांडरमेर

+1। मेरे खेल के लिए जाने का एक अच्छा तरीका लगता है। मैं अपने आप को टाट को गोल करने और तैरने की सभी समस्याओं से दूर रहूँगा।
लुकास तुलीओ

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

3
हालाँकि, बेसिस पॉइंट्स नॉट सेंट्स (जहां 100 बेसिस पॉइंट्स = 1 प्रतिशत) का उपयोग 100 के बजाय 10,000 के कारक के साथ करें। यह GAAP द्वारा सभी वित्तीय, बैंकिंग या लेखा अनुप्रयोगों के लिए आवश्यक है।
पीटर गेकर्न्स 22

66

ठीक है, मैं कूद जाऊंगा।

मेरी सलाह: यह एक खेल है। इसे आसान और उपयोग करें double

यहाँ मेरा तर्क है:

  • floatएक सटीक समस्या है जो लाखों में इकाइयों को जोड़ते समय प्रकट होती है, इसलिए यद्यपि यह सौम्य हो सकता है, मैं उस प्रकार से बचूंगा। doubleकेवल क्विंटिलों (एक बिलियन अरबों) के आसपास समस्याएं शुरू होती हैं।
  • चूंकि आपके पास ब्याज दरें होने वाली हैं, आपको वैसे भी सैद्धांतिक अनंत सटीकता की आवश्यकता होगी: 4% ब्याज दरों के साथ, $ 100 $ 104 हो जाएगा, फिर $ 108.16, फिर $ 112.4864, आदि। यह बनाता है intऔर longबेकार है क्योंकि आप नहीं जानते कि कहां रुकना है दशमलव।
  • BigDecimalआपको मनमाने ढंग से सटीक देगा, लेकिन जब तक आप कुछ समय पर सटीक क्लैंप नहीं करते हैं, तब तक यह धीमी गति से धीमा हो जाएगा। गोलाई के नियम क्या हैं? आप कैसे चुनेंगे कि कहां रुकना है? क्या यह अधिक सटीक बिट्स की तुलना में लायक है double? मैं विश्वास नहीं।

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

व्यावहारिक उदाहरण

मुझे लगता है कि मैं इससे असहमत हूं। यहाँ कुछ अतिरिक्त उदाहरण दिए गए हैं कि मैं क्या मतलब है।

भंडारण : यदि आपकी आधार इकाई शत-प्रतिशत है, तो आप मान संचय करते समय संभवतः निकटतम प्रतिशत पर चक्कर लगाना चाहेंगे:

void SetValue(double v) { m_value = round(v * 100.0) / 100.0; }

इस पद्धति को अपनाने पर आपको बिल्कुल कोई समस्या नहीं होगी, जो पूर्णांक प्रकार के साथ आपके पास नहीं होगी।

पुन : प्राप्त : सभी संगणनाएँ सीधे दोहरे मान पर की जा सकती हैं, जिनमें कोई रूपांतरण नहीं है:

double value = data.GetValue();
value = value / 3.0 * 12.0;
[...]
data.SetValue(value);

ध्यान दें कि यदि आप के doubleसाथ प्रतिस्थापित करते हैं तो उपरोक्त कोड काम नहीं करता है int64_t: जानकारी के संभावित नुकसान के साथ एक अंतर्निहित रूपांतरण होगा double, फिर ट्रंकेशन किया जाएगा। GetValueint64_t ()

तुलना : फ्लोटिंग-पॉइंट प्रकारों के साथ तुलना करने के लिए तुलना एक चीज है। मैं इस तरह के रूप में एक तुलना विधि का उपयोग करने का सुझाव देता हूं:

/* Are values equal to a tenth of a cent? */
bool AreCurrencyValuesEqual(double a, double b) { return abs(a - b) < 0.001; }

गोलाई निष्पक्षता

मान लीजिए कि आपके खाते में 4% ब्याज के साथ $ 9.99 है। खिलाड़ी को कितनी कमाई करनी चाहिए? पूर्णांक राउंडिंग के साथ आपको $ 0.03 मिलता है; फ्लोटिंग-पॉइंट राउंडिंग के साथ आपको $ 0.04 मिलता है। मेरा मानना ​​है कि उत्तरार्द्ध अधिक उचित है।


4
+1। केवल वही स्पष्टीकरण जो मैं जोड़ना चाहता हूं, ठीक उसी तरह जैसे वित्तीय अनुप्रयोग विशिष्ट पूर्वनिर्धारित आवश्यकताओं के अनुरूप होते हैं, इसी तरह गोपन एल्गोरिथ्म भी होता है। यदि खेल एक कैसीनो एक है, तो यह समान मानकों के अनुरूप है और फिर डबल एक विकल्प नहीं है।
Ivaylo Slavov

2
UI को प्रारूपित करने के लिए आपको अभी भी नियमों को गोल करने के बारे में सोचना होगा। क्योंकि हमेशा ऐसे खिलाड़ियों का एक अंश होता है जो एक गेम को एक स्प्रेडशीट के रूप में मानने की कोशिश करेंगे यदि आप अपने बैकएंड का उपयोग नहीं कर रहे हैं, तो वे चिल्लाते हुए और नीचे चिल्लाते हुए लोगों के साथ व्यवहार नहीं करना चाहते हैं। 'गलत' परिणाम उन्हें शांत रखने के लिए आपका सबसे अच्छा विकल्प प्रदर्शित हो रहा है, एक ही आंतरिक और बाहरी प्रतिनिधित्व का उपयोग करना है जिसका अर्थ है एक निश्चित बिंदु प्रारूप का उपयोग करना। जब तक प्रदर्शन एक मुद्दा नहीं बन जाता तब तक BigDecimal ऐसा करने के लिए सबसे अच्छा विकल्प है।
दान नीली

10
मैं इस जवाब से असहमत हूं। गोलाई के मुद्दे दिखाई देते हैं, और यदि वे नीचे जाते हैं, और यदि आप किसी अतिरिक्त गोलाई का उपयोग नहीं कर रहे हैं, तो $ 1.00 अचानक $ 0.99 हो सकता है। लेकिन सबसे महत्वपूर्ण बात, धीमी गति से किया जा रहा मनमाना सटीक दशमलव पूरी तरह अप्रासंगिक है। हम लगभग 2013 में हैं, और जब तक आप बड़े कारक नहीं कर रहे हैं, तो हजारों अंकों के साथ कई लाखों की संख्या में सामान या लॉगरिदम को ट्रिगर करें, आप कभी भी प्रदर्शन में सेंध नहीं देखेंगे। वैसे भी, सरल हमेशा सबसे अच्छा होता है, इसलिए मेरी सिफारिश है कि सभी नंबरों को सेंट के रूप में संग्रहीत किया जाए। इस तरह वे सभी int_64tएस।
पांडा पजामा

8
@Sam पिछली बार जब मैंने अपना बैंक खाता चेक किया था, तो मेरा बैलेंस .0000000000000001 में समाप्त नहीं हुआ था। वास्तविक मुद्रा प्रणाली को गैर-विभाज्य इकाइयों के साथ काम करना चाहिए, और यह पूर्ण रूप से पूर्णांक के साथ दर्शाया गया है। यदि आपको मुद्रा विभाजन सही ढंग से करना चाहिए (जो वास्तव में वास्तविक वित्तीय दुनिया में बिल्कुल भी सामान्य नहीं हैं), तो आपको उन्हें करना होगा ताकि पैसा खो न जाए। उदाहरण के लिए 10/3 = 3+3+4या 10/3 = 3+3+3 (+1)। अन्य सभी ऑपरेशनों के लिए पूर्णांक फ्लोटिंग पॉइंट के विपरीत पूरी तरह से काम करते हैं, जो किसी भी ऑपरेशन में गोलाई की समस्या प्राप्त कर सकते हैं।
पांडा पायजामा

2
@ शमशवर 999 * 4/100। जहां नियमन द्वारा निर्धारित नहीं किया जाता है, सभी पक्ष बैंकों के पक्ष में किए जाएंगे।
डैन नीली

21

जावा में फ्लोटिंग पॉइंट प्रकार ( float, double) एक मुख्य कारण के कारण मुद्राओं के लिए अच्छा प्रतिनिधित्व नहीं है - गोलाई में एक मशीन त्रुटि है। यहां तक ​​कि अगर एक साधारण गणना एक पूर्ण संख्या लौटाती है - जैसे 12.0/2(6.0), फ़्लोटिंग पॉइंट गलत तरीके से इसे गोल कर सकता है ( 6.0000000000001या इन प्रकारों के विशिष्ट प्रतिनिधित्व को स्मृति में) 5.999999999999998या इसी तरह। यह विशिष्ट मशीन गोलाई का एक परिणाम है जो प्रोसेसर में होता है और यह कंप्यूटर के लिए अद्वितीय है जिसने इसकी गणना की। आमतौर पर, यह शायद ही कभी इन मुद्दों के साथ काम करने के लिए एक समस्या है, क्योंकि त्रुटि काफी लापरवाही है, लेकिन उपयोगकर्ता को यह प्रदर्शित करने के लिए एक दर्द है।

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

यदि आपको उच्च उत्पादकता की आवश्यकता है, तो आप बेहतर प्रकारों से चिपके रहेंगे। यदि आप महत्वपूर्ण वित्तीय डेटा के साथ काम करते हैं , और प्रत्येक प्रतिशत महत्वपूर्ण है (जैसे एक विदेशी मुद्रा आवेदन, या कुछ कैसीनो गेम) तो मैं आपको उपयोग करने Longया करने की सलाह दूंगा longLongआपको बड़ी मात्रा और अच्छी परिशुद्धता को संभालने की अनुमति देगा। मान लें कि आपको अपनी आवश्यकता है, कहते हैं, दशमलव बिंदु के बाद 4 अंक, आपको केवल 10000 से राशि गुणा करने की आवश्यकता है। ऑन-लाइन कैसीनो खेलों के विकास में अनुभव होने के बाद, मैंने Longअक्सर सेंट में पैसे का प्रतिनिधित्व करने के लिए उपयोग किया है । विदेशी मुद्रा अनुप्रयोगों में, परिशुद्धता अधिक महत्वपूर्ण है, इसलिए आपको अधिक से अधिक गुणक की आवश्यकता होगी - फिर भी, पूरे नंबर मशीन राउंडिंग मुद्दों से मुक्त हैं (बेशक 3/2 की तरह मैनुअल राउंडिंग आपको खुद को संभालना चाहिए)।

एक स्वीकार्य विकल्प मानक फ़्लोटिंग पॉइंट प्रकारों का उपयोग करना होगा - Floatऔर Double, यदि प्रदर्शन सटीकता से सौ प्रतिशत तक अधिक महत्वपूर्ण है। फिर, अपने प्रदर्शन तर्क पर, आपको बस एक पूर्वनिर्धारित स्वरूपण का उपयोग करने की आवश्यकता है , ताकि संभावित मशीन राउंडिंग की बदसूरती उपयोगकर्ता को न मिले।


4
+1 विवरण: "मान लें कि आपको अपनी आवश्यकता है, दशमलव बिंदु के बाद 4 अंक कहते हैं, आपको केवल 1000 की राशि को गुणा करना है।" -> इसे निश्चित बिंदु कहा जाता है।
लॉरेंट कौविदो

1
@Sam, उदाहरण हिस्सेदारी के लिए नंबर प्रदान किए गए थे। फिर भी, मैंने व्यक्तिगत रूप से ऐसे सरल नंबरों के साथ अजीब परिणाम देखे हैं, लेकिन यह लगातार परिदृश्य नहीं है। जब फ्लोटिंग पॉइंट खेलने के लिए आते हैं, तो यह संभवतः होने की अधिक संभावना है, लेकिन स्पॉट करने की संभावना अधिक नहीं है
Iv39lo Slavov

2
@ इवलो स्लाव, मैं आपसे सहमत हूं। मेरे जवाब में मैंने सिर्फ अपनी राय दी। मुझे चर्चा करना पसंद है और सही चीज़ लेने की इच्छा है। आपकी राय के लिए भी धन्यवाद। :)
एमडी महबूबुर्रहमान

1
@ समोसेश्वर: यह तर्क सभी मामलों में काम नहीं करता है। देखें: ideone.com/nI2ZOK
समरसा

1
@ समोसेश्वर: इसकी कोई गारंटी नहीं है। सीमा के भीतर की संख्याएँ जो अभी भी पूरी संख्या में हैं, पहले डिवीजन पर त्रुटि जमा करना शुरू करती हैं: ideone.com/AKbR7i
समोरसा

17

के लिए छोटे पैमाने पर खेल और जहां प्रक्रिया की गति, स्मृति महत्वपूर्ण मुद्दा (परिशुद्धता या गणित सह प्रोसेसर के साथ काम दर्दनाक धीमी गति से कर सकते हैं के कारण) है, वहाँ दोगुना पर्याप्त है।

लेकिन बड़े पैमाने पर खेलों के लिए (उदाहरण के लिए, सामाजिक खेल) और जहां प्रक्रिया की गति, मेमोरी सीमित नहीं है, वहां बिगडेक्लेम बेहतर है। क्योंकि यहाँ,

  • मौद्रिक गणना के लिए int या लंबा।
  • फ़्लोट्स और डबल्स अधिकांश बेस 10 वास्तविक संख्याओं का सही प्रतिनिधित्व नहीं कर सकते हैं।

संसाधन:

से https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency

क्योंकि फ़्लोट्स और डबल्स अधिकांश बेस 10 वास्तविक संख्याओं का सही प्रतिनिधित्व नहीं कर सकते हैं।

यह कैसे IEEE-754 फ़्लोटिंग-पॉइंट नंबर काम करता है: यह साइन के लिए थोड़ा सा, एक एक्सपोनेंट को स्टोर करने के लिए कुछ बिट्स और वास्तविक अंश के लिए बाकी है। यह १.४५ * १० ^ ४ के समान रूप में संख्याओं का प्रतिनिधित्व करता है; सिवाय इसके कि आधार के 10 होने के बजाय, यह दो है।

सभी वास्तविक दशमलव संख्याएं वास्तव में, दस की शक्ति के सटीक अंश के रूप में देखी जा सकती हैं। उदाहरण के लिए, 10.45 वास्तव में 1045/10 ^ 2 है। और जिस तरह कुछ अंशों को दस की शक्ति के अंश के रूप में प्रस्तुत नहीं किया जा सकता है (1/3 के मन में आता है), उनमें से कुछ को दो की शक्ति के एक अंश के रूप में बिल्कुल प्रतिनिधित्व नहीं किया जा सकता है। एक साधारण उदाहरण के रूप में, आप बस एक फ्लोटिंग-पॉइंट चर के अंदर 0.1 स्टोर नहीं कर सकते। आपको निकटतम प्रतिनिधित्व योग्य मान मिलेगा, जो कि 0.0999999999999999996 की तरह कुछ है, और इसे प्रदर्शित करते समय सॉफ्टवेयर 0.1 पर गोल हो जाएगा।

हालाँकि, जब आप अधिक संख्याओं पर अधिक जोड़, घटाव, गुणा और भाग करते हैं, तो छोटी त्रुटियों को जोड़ते हुए आप अधिक से अधिक सटीकता खो देंगे। यह पैसे से निपटने के लिए फ्लोट और युगल को अपर्याप्त बनाता है, जहां सही सटीकता की आवश्यकता होती है।

बलोच, जे। से, प्रभावी जावा, दूसरा संस्करण, 48:

The float and double types are particularly ill-suited for 

मौद्रिक गणना क्योंकि एक फ्लोट या डबल के रूप में 0.1 (या दस की किसी भी अन्य नकारात्मक शक्ति) का प्रतिनिधित्व करना असंभव है।

For example, suppose you have $1.03 and you spend 42c. How much money do you have left?

System.out.println(1.03 - .42);

prints out 0.6100000000000001.

The right way to solve this problem is to use BigDecimal, 

मौद्रिक गणना के लिए int या लंबा।

पर भी एक नजर


मैं केवल उस भाग से असहमत हूं जो लंबे समय तक छोटी गणनाओं के लिए उपयुक्त है। मेरे वास्तविक जीवन के अनुभव में, यह अच्छी सटीकता और बड़ी मात्रा में पैसे को संभालने के लिए पर्याप्त साबित हुआ है। हां, यह उपयोग करने के लिए थोड़ा बोझिल हो सकता है लेकिन यह दो महत्वपूर्ण बिंदुओं में बिगडेसिमल को हराता है - 1) यह तेज है (बिगडेसिमल सॉफ्टवेयर गोलाई का उपयोग करता है, जो कि धीमी गति से निर्मित सीपीयू गोलाई में फ्लोटिंग / डबल का उपयोग करता है) और 2) बिगडेसीमल सटीक खोए बिना डेटाबेस में बने रहना कठिन है - सभी डेटाबेस ऐसे 'कस्टम' प्रकार का समर्थन नहीं करते हैं। लंबे समय से सभी प्रमुख डेटाबेस पर अच्छी तरह से जाना जाता है और व्यापक रूप से समर्थित है।
Ivaylo Slavov

@ इवालो स्लाव, मेरी गलती के लिए क्षमा करें। मैंने अपना उत्तर अपडेट कर दिया है।
Md महबूबुर्रहमान

एक ही समस्या के लिए एक अलग दृष्टिकोण देने के लिए कोई माफी की आवश्यकता नहीं है :)
Ivaylo Slavov

2
@ इवलो स्लाव, मैं आपसे सहमत हूं। मेरे जवाब में मैंने सिर्फ अपनी राय दी। मुझे चर्चा करना पसंद है और सही चीज़ लेने की इच्छा है। आपकी राय के लिए भी धन्यवाद। :)
एमडी महबूबुर्रहमान

इस साइट का उद्देश्य मुद्दों को स्पष्ट करना और विशिष्ट परिदृश्य के आधार पर ओपी को सही निर्णय लेने में मदद करना है। हम केवल इस प्रक्रिया को गति देने में मदद कर सकते हैं :)
Ivaylo Slavov

13

आप कम से कम एक बैकअप के रूप में अपनी मुद्रा को स्टोर करना चाहते हैं longऔर अपनी मुद्रा की गणना करना चाहते हैं double। आप सभी चाहते हैं लेनदेन के रूप में जगह लेने के लिए long

जिस कारण से आप अपनी मुद्रा को स्टोर करना चाहते हैं, longवह यह है कि आप किसी भी मुद्रा को खोना नहीं चाहते हैं।

मान लीजिए कि आप एक का उपयोग करते हैं double, और आपके पास कोई पैसा नहीं है। कोई आपको तीन डिम देता है, और फिर उन्हें वापस ले जाता है।

You:       0.1+0.1+0.1-0.1-0.1-0.1 = 2.7755575615628914E-17

खैर, यह इतना अच्छा नहीं है। हो सकता है कि $ 10 वाले कोई व्यक्ति पहले आपको तीन बार दे कर अपना भाग्य दूर करना चाहता हो, और फिर $ 9.70 किसी और को दे रहा हो।

Them: 10.0-0.1-0.1-0.1-9.7 = 1.7763568394002505E-15

और फिर आप उन्हें वापस दे देते हैं:

Them: ...+0.1+0.1+0.1 = 0.3000000000000018

यह अभी टूटी है।

अब, चलो एक लंबे समय का उपयोग करते हैं, और हम दसियों सेंट्स (इसलिए 1 = $ 0.001) का ट्रैक रखेंगे। आइए ग्रह पर सभी को एक अरब, एक सौ बारह मिलियन, पचहत्तर हजार, एक सौ तैंतालीस डॉलर देते हैं:

Us: 7000000000L*1112075143000L = 1 894 569 218 048

उम, रुको, हम सभी को एक अरब डॉलर से अधिक दे सकते हैं, और केवल दो पर थोड़ा खर्च कर सकते हैं? यहां ओवरफ्लो एक आपदा है।

इसलिए, जब भी आप किसी धनराशि की गणना के लिए स्थानांतरण, उपयोग करें doubleऔर Math.roundइसे प्राप्त करें long। फिर उपयोग करके शेष राशि को जोड़ें (दोनों खातों को जोड़ें और घटाएं) long

आपकी अर्थव्यवस्था लीक नहीं होगी, और यह एक क्वाड्रिलियन डॉलर तक बढ़ जाएगी।

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

* आप गणना करते हैं कि एक भुगतान क्या है, इसके लिए गोल long; फिर से गुणा 20.0करें और जांचें कि यह सीमा में है; यदि ऐसा है, तो आप 20Lअपनी शेष राशि में से कटौती के लिए भुगतान को गुणा करते हैं । सामान्य तौर पर, सभी लेन-देन के रूप में संभाला जाना चाहिए long, इसलिए आपको वास्तव में सभी व्यक्तिगत लेनदेन को योग करने की आवश्यकता है; आप एक शॉर्टकट के रूप में गुणा कर सकते हैं, लेकिन आपको यह सुनिश्चित करने की आवश्यकता है कि आप गोलाई की त्रुटियों को नहीं जोड़ते हैं और आप अतिप्रवाह नहीं करते हैं, जिसका अर्थ है कि आपको doubleवास्तविक गणना करने से पहले जांच करनी होगी long


8

मैं यह कहना चाहूंगा कि उपयोगकर्ता को प्रदर्शित होने वाला कोई भी मूल्य लगभग हमेशा पूर्णांक होना चाहिए। पैसा ही इसका सबसे प्रमुख उदाहरण है। एक राक्षस को 900 एचपी के साथ 225 नुकसान का सामना करना और यह पता लगाना कि उसके पास अभी भी 1 एचपी शेष है, अनुभव से केवल उतना ही घटेगा जितना कि आप किसी चीज को दर्ज करने से कम एक पैसे के अदृश्य अंश हैं।

अधिक तकनीकी पक्ष पर मुझे लगता है कि यह ध्यान देने योग्य है कि किसी को ब्याज जैसी उन्नत सामग्री करने के लिए तैरने के लिए वापस नहीं जाना पड़ता है। जब तक आपको अपने चुने हुए पूर्णांक प्रकार में पर्याप्त हेडरूम मिल गया है और एक विभाजन दशमलव संख्या से गुणा के लिए खड़ा होगा, उदाहरण के लिए 4% जोड़ने के लिए, नीचे गोल:

number=(number*104)/100

4% जोड़ने के लिए, मानक सम्मेलनों द्वारा गोल:

number=(number*104+50)/100

यहां कोई फ्लोट पॉइंट अशुद्धि नहीं है, गोलाई हमेशा .5निशान पर बिल्कुल विभाजित होती है ।

संपादित करें, असली सवाल:

यह देखते हुए कि बहस कैसे चली गई है, मैं यह सोचना शुरू करता हूं कि सवाल क्या है, यह रेखांकित करना एक सरल int/ floatउत्तर की तुलना में अधिक उपयोगी हो सकता है । प्रश्न के मूल में यह डेटा प्रकारों के बारे में नहीं है, यह एक कार्यक्रम के विवरण को नियंत्रित करने के बारे में है।

एक पूर्णांक मान का प्रतिनिधित्व करने के लिए एक पूर्णांक का उपयोग प्रोग्रामर को कार्यान्वयन विवरण से निपटने के लिए मजबूर करता है। "क्या सटीक उपयोग करने के लिए?" और "किस तरह गोल?" ऐसे प्रश्न हैं जिनका उत्तर स्पष्ट रूप से दिया जाना चाहिए।

दूसरी ओर एक फ्लोट प्रोग्रामर को चिंता करने के लिए मजबूर नहीं करता है, यह पहले से ही बहुत अधिक करता है जो कोई उम्मीद करेगा। लेकिन चूंकि फ्लोट अनंत परिशुद्धता नहीं है, इसलिए कुछ राउंडिंग होगी, और यह राउंडिंग बहुत अप्रत्याशित है।

एक प्रयोग में क्या होता है तैरता है और गोलाई पर नियंत्रण रखना चाहता है? यह लगभग असंभव हो जाता है। एक फ्लोट बनाने का एकमात्र तरीका वास्तव में अनुमानित है केवल उन मूल्यों का उपयोग करना है जिन्हें पूरे 2^nएस में दर्शाया जा सकता है । लेकिन यह निर्माण फ्लोट्स को उपयोग करने में काफी कठिन बनाता है।

इस प्रकार सरल प्रश्न का उत्तर है: यदि आप नियंत्रण लेना चाहते हैं, तो पूर्णांक का उपयोग करें, यदि नहीं, तो फ़्लोट का उपयोग करें।

लेकिन जिस सवाल पर बहस हो रही है, वह सवाल का दूसरा रूप है: क्या आप नियंत्रण रखना चाहते हैं?


5

यहां तक ​​कि अगर यह "केवल एक खेल" है, तो मैं मार्टिन फाउलर से मनी पैटर्न का उपयोग करूंगा , जो लंबे समय तक समर्थित होगा।

क्यों?

स्थानीयकरण (L10n): उस पैटर्न का उपयोग करके आप आसानी से अपनी खेल मुद्रा का स्थानीयकरण कर सकते हैं। "टायकून टाइकून" जैसे पुराने टाइकून खेलों के बारे में सोचें। वे आसानी से खिलाड़ी को वास्तविक विश्व मुद्रा को पूरा करने के लिए इन-गेम मुद्रा (अर्थात ब्रिटिश पाउंड से यूएस डॉलर) में बदलने की अनुमति देते हैं।

तथा

लंबा डेटा प्रकार 64-बिट हस्ताक्षरित दो के पूरक पूर्णांक है। इसका न्यूनतम मूल्य -9,223,372,036,854,775,808 और अधिकतम मूल्य 9,223,372,036,854,775,807 (सम्मिलित) ( जावा ट्यूटोरियल ) है।

इसका मतलब है कि आप 9,000 गुना वर्तमान एम 2 यूएस मनी सप्लाई (~ 10,000 बिलियन डॉलर) स्टोर कर सकते हैं । आपको किसी भी अन्य विश्व मुद्रा का उपयोग करने के लिए पर्याप्त जगह दे रहा है, शायद, यहां तक ​​कि जिनके पास हाइपरिनफ्लेशन है (यदि उत्सुक हैं, तो WW -WWI जर्मन मुद्रास्फीति देखें , जहां 1 पाउंड रोटी 3,000,000,000 अंक थी)

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


2

आप इसमें कितना काम करना चाहते हैं? सटीकता कितनी महत्वपूर्ण है? क्या आप चक्करदार के साथ होने वाली भिन्नात्मक त्रुटियों को ट्रैक करने और द्विआधारी प्रणाली में दशमलव संख्याओं का प्रतिनिधित्व करने की असंभवता के बारे में परवाह करते हैं?

अंततः मैं "कॉर्नर मामलों" और ज्ञात समस्याग्रस्त मामलों के लिए यूनिट परीक्षणों को कोडिंग और कार्यान्वित करने के लिए थोड़ा और समय बिताने की ओर रुख करता हूं - इसलिए मैं एक संशोधित बिगइन्टेगर के संदर्भ में सोच रहा हूं, जिसमें बड़ी मात्रा में मध्यस्थता शामिल है और या तो बिगडेसिमल के साथ फ्रैक्चर बिट्स को बनाए रखता है। एक BigRational भाग (दो BigIntegers, हर के लिए एक और अंश के लिए दूसरा) - और भिन्नात्मक भाग को मुख्य Bigtteger में किसी भी गैर-भिन्नात्मक भाग को जोड़कर (शायद केवल समय-समय पर) एक वास्तविक अंश रखने के लिए कोड शामिल करता है। फिर मैं आंतरिक रूप से जीयूआई गणना से आंशिक भागों को बाहर रखने के लिए सेंट में सब कुछ का ट्रैक रखेगा।

संभवतः (सरल) खेल के लिए जटिल तरीका है - लेकिन खुले स्रोत के रूप में प्रकाशित पुस्तकालय के लिए अच्छा है! बस भिन्नात्मक बिट्स के साथ काम करते समय प्रदर्शन को अच्छा रखने के तरीकों का पता लगाना होगा ...


1

निश्चित रूप से तैरता नहीं है। केवल 7 अंकों के साथ, आपके पास केवल सटीकता है जैसे:

12,345.67 123,456.7x

तो आप देखते हैं, पहले से ही 10 ^ 5 डॉलर के साथ, आप पेनी का ट्रैक खो रहे हैं। डबल खेल उद्देश्यों के लिए प्रयोग करने योग्य है, सटीकता की चिंताओं के कारण वास्तविक जीवन में नहीं।

लेकिन अगर आप लेन-देन पर नज़र रखने जा रहे हैं और इसे संक्षिप्त करने जा रहे हैं तो लंबे समय तक (और मेरा मतलब है कि 64 बिट, या सी ++ में लंबे समय तक) पर्याप्त नहीं है। यह किसी भी कंपनी की शुद्ध पकड़ को बनाए रखने के लिए पर्याप्त है, लेकिन एक साल के लिए सभी लेनदेन अतिप्रवाह कर सकते हैं। यह निर्भर करता है कि खेल में आपकी वित्तीय "दुनिया" कितनी बड़ी है।


0

एक और समाधान मैं यहां जोड़ूंगा एक पैसा वर्ग बनाना है। कक्षा कुछ इस तरह होगी (केवल एक संरचना भी हो सकती है)।

class Money
{
     string currencyType; //the type of currency example USD could be an enum as well
     bool isNegativeValue;
     unsigned long int wholeUnits;
     unsigned short int partialUnits;
}

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

इसे आगे पूरी इकाइयों की संख्या जैसी आंशिक चीज़ों को शामिल करने के लिए विस्तारित किया जा सकता है ताकि आपके पास ऐसी मुद्राएं हों जो 100 उप इकाइयों के अलावा किसी अन्य चीज़ पर उपविभाजित हों, इस मामले में प्रति डॉलर। उदाहरण के लिए, आपके पास एक 125 फ़्लॉपी हो सकते हैं।

संपादित करें:

मैं इस विचार का विस्तार करूंगा कि आपके पास एक प्रकार की तालिका भी हो सकती है, जो कि धन वर्ग तक पहुंच सकता है जो अन्य सभी मुद्राओं के मुकाबले मुद्रा विनिमय दर प्रदान करेगा। आप इसे अपने ऑपरेटर ओवरलोडिंग कार्यों में बना सकते हैं। इसलिए, यदि आप स्वचालित रूप से 4 USD को 4 ब्रिटिश पाउंड में जोड़ने का प्रयास करते हैं, तो यह आपको स्वचालित रूप से 6.6 पाउंड (लेखन के रूप में) देगा।


0

जैसा कि आपके मूल प्रश्न पर एक टिप्पणी में उल्लेख किया गया है, इस मुद्दे को StackExchange: https://stackoverflow.com/questions/8148684/what-is-the-best-data-type-to-use-for- पर कवर किया गया है। पैसा-इन-जावा-ऐप

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


-1

कक्षा का उपयोग करें यह सबसे अच्छा तरीका है। आप अपने पैसे के कार्यान्वयन को छिपा सकते हैं जिसे आप किसी भी समय डबल / लंबे समय तक स्विच कर सकते हैं।

उदाहरण

class Money
{
    private long count;//Store here what ever you want in what type you want i suggest long or int
    //methods constructors etc.
    public String print()
    {
        return count/100.F; //convert this to string
    }
}

आपके कोड उपयोग में बस गेट्टर यह बेहतर तरीका है जो मुझे लगता है और आप अधिक उपयोगी तरीके स्टोर कर सकते हैं।

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