মুদ্রার প্রতিনিধিত্ব করতে ডাবল বা ফ্লোট ব্যবহার করবেন না কেন?


938

আমাকে সর্বদা বলা হয়েছে যে কখনও অর্থ doubleবা floatপ্রকারের সাথে প্রতিনিধিত্ব করবেন না এবং এবার আমি আপনার কাছে প্রশ্ন উত্থাপন করছি: কেন?

আমি নিশ্চিত যে খুব ভাল কারণ আছে, আমি কেবল এটি জানি না।


4
এই এই প্রশ্নটি দেখুন: রাউন্ডিং ত্রুটিগুলি?
জেফ ওগটা

80
কেবল স্পষ্ট করে বলতে গেলে, এগুলি এমন কোনও কিছুর জন্য ব্যবহার করা উচিত নয় যা কেবল মুদ্রার জন্য নয় currency
জেফ

152
নির্ভুলতার প্রয়োজন এমন কোনও কিছুর জন্য তাদের ব্যবহার করা উচিত নয় । তবে ডাবলের 53 টি তাত্পর্যপূর্ণ বিট (~ 16 ডেসিমাল ডিজিট) কেবলমাত্র সঠিকতার জন্য প্রয়োজনীয় জিনিসগুলির পক্ষে যথেষ্ট ভাল ।
dan04

21
@ জেফ আপনার মন্তব্যটি কোন বাইনারি ভাসমান-পয়েন্টের পক্ষে ভাল এবং কোনটি ভাল নয় তা সম্পূর্ণরূপে ভুলভাবে উপস্থাপন করে। নীচে zneak দ্বারা উত্তর পড়ুন, এবং আপনার বিভ্রান্তিমূলক মন্তব্য মুছুন।
পাসকেল কুয়াক

উত্তর:


983

কারণ ফ্লোটস এবং ডাবলস আমরা অর্থের জন্য ব্যবহার করি বেস 10 গুণগুলি সঠিকভাবে উপস্থাপন করতে পারে না। এই সমস্যাটি কেবল জাভার নয়, এটি এমন কোনও প্রোগ্রামিং ভাষার জন্য যা বেস 2 ভাসমান-পয়েন্টের ধরণের ব্যবহার করে।

বেস 10 এ, আপনি 1025 * 10 -2 হিসাবে 10.25 লিখতে পারেন ( 10 এর একটি পূর্ণসংখ্যার বার গুণ)। আইইইই-754৪ ভাসমান-পয়েন্ট সংখ্যাগুলি পৃথক, তবে তাদের সম্পর্কে ভাবার একটি খুব সহজ উপায় হ'ল পরিবর্তে দুটি দ্বারা গুণিত করা। উদাহরণস্বরূপ, আপনি 164 * 2 -4 ( দুটি সংখ্যার পূর্ণসংখ্যার বার) এর দিকে তাকিয়ে থাকতে পারেন যা 10.25 এর সমান। সংখ্যাগুলি মেমোরিতে কীভাবে উপস্থাপিত হয় তা নয়, তবে গণিতের প্রভাবগুলিও একই।

এমনকি বেস 10 এ, এই স্বরলিপিটি সবচেয়ে সাধারণ ভগ্নাংশকে সঠিকভাবে উপস্থাপন করতে পারে না। উদাহরণস্বরূপ, আপনি 1/3 উপস্থাপন করতে পারবেন না: দশমিক প্রতিনিধিত্ব পুনরাবৃত্তি করছে (0.3.33 ...), সুতরাং কোনও সীমাবদ্ধ পূর্ণসংখ্যা নেই যা আপনি 10 এর পাওয়ার দ্বারা 1/3 পেতে গুণতে পারেন। আপনি ৩৩ এর একটি দীর্ঘ ক্রম এবং 333333333 * 10 এর মতো একটি ক্ষুদ্র ঘোষককে স্থির করতে পারেন -10 এর মতো , তবে এটি সঠিক নয়: আপনি যদি এটি 3 দিয়ে গুণ করেন তবে আপনি 1 পাবেন না।

যাইহোক, অর্থ গণনা করার উদ্দেশ্যে, কমপক্ষে দেশগুলির জন্য যাদের অর্থ মার্কিন ডলারের প্রস্থের অর্ডারের মধ্যে মূল্যবান হয়, সাধারণত আপনার প্রয়োজন সমস্ত হ'ল 10 এর গুণক সঞ্চয় করতে সক্ষম হবেন -2 এর গুণকগুলি , তাই এটি আসলে কোনও ব্যাপার নয় doesn't যে 1/3 উপস্থাপন করা যাবে না।

ফ্লোটস এবং ডাবলসের সমস্যা হ'ল বেশীরভাগ টাকা মত সংখ্যার একটি পূর্ণসংখ্যা গুন একটি সঠিক উপস্থাপনা 2. আসলে একটি শক্তি, 0 এবং 1 এর মধ্যে 0.01 একমাত্র গুণিতক (যা যখন ডিলিং গুরুত্বপূর্ণ হবে না অর্থের সাথে কারণ তারা পূর্ণসংখ্যার সেন্ট) যা আইইইই-75৫৪ বাইনারি ভাসমান-পয়েন্ট সংখ্যা হিসাবে ঠিক উপস্থাপন করা যেতে পারে 0, 0.25, 0.5, 0.75 এবং 1 অন্যান্য সমস্ত অল্প পরিমাণে বন্ধ রয়েছে। ০.৩৩৩৩৩৩ উদাহরণের সাদৃশ্য হিসাবে, আপনি যদি 0.1 এর জন্য ভাসমান-পয়েন্ট মান নেন এবং আপনি এটি 10 ​​দিয়ে গুণ করেন তবে আপনি 1 পাবেন না।

একটি হিসাবে অর্থ উপস্থাপন করা doubleবা floatসম্ভবত প্রথমে দেখতে ভাল হিসাবে সফ্টওয়্যার ক্ষুদ্র ত্রুটিগুলি সরিয়ে দেয়, তবে আপনি যেমন আরও সংযোজন, বিয়োগ, গুণ এবং বিয়োগ সংখ্যক বিভাজনগুলি সম্পাদন করেন ত্রুটিগুলি আরও জটিল হয়ে উঠবে এবং আপনি দৃশ্যমান মানের সাথে শেষ হবেন you'll সঠিক না. এটি অর্থের সাথে লেনদেনের জন্য ভাসমান এবং ডাবল অপর্যাপ্ত করে তোলে, যেখানে বেস 10 শক্তির বহুগুণের জন্য নিখুঁত নির্ভুলতা প্রয়োজন।

কোনও সমাধান যে কোনও ভাষাতেই কাজ করে তা হ'ল পরিবর্তে পূর্ণসংখ্যা এবং সেন্ট গণনা। উদাহরণস্বরূপ, 1025 হবে $ 10.25। বেশ কয়েকটি ভাষায় অর্থোপার্জনের জন্য অন্তর্নির্মিত প্রকার রয়েছে। অন্যগুলির মধ্যে, জাভা BigDecimalক্লাস রয়েছে, এবং সি # decimalটাইপ রয়েছে।


3
@ ফ্রান আপনি রাউন্ডিং ত্রুটি পাবেন এবং এমন কিছু ক্ষেত্রে যেখানে প্রচুর পরিমাণে মুদ্রা ব্যবহৃত হচ্ছে, সুদের হারের গণনা সম্পূর্ণভাবে বন্ধ করা যাবে
লিনাক্সুজার ২

5
... বেশিরভাগ বেস 10 ভগ্নাংশ, এটি। উদাহরণস্বরূপ, 0.1 এর সঠিক বাইনারি ভাসমান-পয়েন্ট উপস্থাপনা নেই। সুতরাং, 1.0 / 10 * 101.0 এর মতো নাও হতে পারে।
ক্রিস জেস্টার-ইয়ং

6
@ linuxuser27 আমার মনে হয় ফ্রান মজার হওয়ার চেষ্টা করছিল। যাইহোক, জিনাকের উত্তরটি আমি দেখেছি সেরা, এটি ব্লচের ক্লাসিক সংস্করণের চেয়েও ভাল।
আইজাক রবিনোভিচ

5
অবশ্যই আপনি যদি নির্ভুলতাটি জানেন তবে আপনি সর্বদা ফলাফলটি ঘিরে ফেলতে পারেন এবং এভাবে পুরো বিষয়টি এড়িয়ে যেতে পারেন। এটি বিগডিসিমাল ব্যবহারের চেয়ে অনেক দ্রুত এবং সহজ। অন্য বিকল্প হ'ল স্থির নির্ভুলতা অবধি বা দীর্ঘ ব্যবহার করা।
পিটার লরি

2
@ জেনাক আপনি কি জানেন যে মূলদ সংখ্যাগুলি আসল সংখ্যার একটি উপসেট , তাই না? আইইইই-754 বাস্তব সংখ্যার হয় বাস্তব নম্বর। তারা শুধু ঘটতে এছাড়াও মূলদ হও।
টিম সেগুইন

314

ব্লচ, জে।, কার্যকর জাভা, ২ য় সংস্করণ, আইটেম 48:

floatএবং doubleধরনের বিশেষ করে আর্থিক হিসাব জন্য মন্দ উপযুক্ত কারণ এটা অসম্ভব হিসেবে 0.1 (অথবা দশ অন্য কোন নেতিবাচক ক্ষমতা) প্রতিনিধিত্ব করতে floatবা doubleঠিক।

উদাহরণস্বরূপ, ধরুন আপনার কাছে $ 1.03 এবং আপনি 42c ব্যয় করেন। তুমি কত টাকা রেখেছ?

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

প্রিন্ট আউট 0.6100000000000001

এই সমস্যার সমাধান করার সঠিক উপায় ব্যবহার করা BigDecimal, intবা long আর্থিক হিসাব জন্য।

যদিও BigDecimalকিছু সতর্কতা রয়েছে (দয়া করে বর্তমানে গৃহীত উত্তর দেখুন)।


6
আর্থিক হিসাবের জন্য আন্ত বা দীর্ঘ ব্যবহারের পরামর্শ দিয়ে আমি কিছুটা বিভ্রান্ত। আপনি কোন প্রকার বা দীর্ঘ হিসাবে 1.03 উপস্থাপন করবেন? আমি "দীর্ঘ a = 1.04" চেষ্টা করেছি; এবং "দীর্ঘ a = 104/100;" কোন লাভ নেই।
পিটার

49
@ পিটার, আপনি long a = 104ডলারের পরিবর্তে সেন্টে গণনা এবং গণনা করুন।
জিনাক

@Zneak যখন শতাংশকে যৌগিক সুদ বা অনুরূপ প্রয়োগ করা দরকার তখন কী হবে?
trusktr

3
@ ট্রস্ক্রিট, আমি আপনার প্ল্যাটফর্মের দশমিক ধরণের সাথে যাব। জাভাতে, এটি BigDecimal
জিনাক করুন

13
@ মার্টিনাস ... এবং আপনি কি মনে করেন না যে এই জাতীয় জিনিসগুলির জন্য দ্বিগুণ ব্যবহার করা ত্রুটি-ঝুঁকির মতো? আমি দেখেছি ভাসা রাউন্ডইং ইস্যু বাস্তব ব্যবস্থা আঘাত কঠিন । এমনকি ব্যাংকিংয়েও। দয়া করে এটির সুপারিশ করবেন না, বা আপনি যদি করেন তবে আলাদা উত্তর হিসাবে সরবরাহ করুন (যাতে আমরা এটি ডাউনভিট করতে পারি: পি)
ইইস

74

এটি নির্ভুলতার বিষয় নয়, এটি নির্ভুলতার বিষয়ও নয়। বেস 2 এর পরিবর্তে গণনার জন্য বেস 10 ব্যবহার করা মানুষের প্রত্যাশা পূরণের বিষয়টি উদাহরণস্বরূপ, আর্থিক গণনার জন্য দ্বিগুণ ব্যবহার করা কোনও গাণিতিক দিক থেকে "ভুল" এমন উত্তর তৈরি করে না, তবে এটি উত্তরগুলি তৈরি করতে পারে যা হ'ল আর্থিক দিক থেকে যা প্রত্যাশিত তা নয়।

এমনকি যদি আপনি আউটপুটের আগে শেষ মুহুর্তে আপনার ফলাফলগুলি সরিয়ে নেন, আপনি এখনও মাঝে মধ্যে ডাবলগুলি ব্যবহার করে ফল পেতে পারেন যা প্রত্যাশার সাথে মেলে না।

একটি ক্যালকুলেটর ব্যবহার করে, বা হাতে হাতে ফলাফল গণনা করা হচ্ছে, ঠিক 1.40 * 165 = 231। তবে অভ্যন্তরীণভাবে আমার সংকলক / অপারেটিং সিস্টেমের পরিবেশে ডাবলগুলি ব্যবহার করে এটি 230.99999 এর কাছাকাছি বাইনারি নম্বর হিসাবে সঞ্চিত হয় ... সুতরাং আপনি যদি সংখ্যাটি কেটে ফেলেন তবে আপনি 231 এর পরিবর্তে 230 পেয়ে যাবেন You আপনি কারণটি কাটানোর পরিবর্তে গোল করতে পারেন 231 এর কাঙ্ক্ষিত ফলাফল দিয়েছে That এটি সত্য, তবে বৃত্তাকারে সর্বদা কাটা কাটা জড়িত। আপনি যে কোনও রাউন্ডিং টেকনিক ব্যবহার করেন না কেন, এখনও এর মতো সীমানা পরিস্থিতি রয়েছে যা আপনি যখন এটির চারপাশের প্রত্যাশা করবেন তখন গোল হয়ে যাবে। এগুলি যথেষ্ট বিরল যে তারা প্রায়শই ক্যাজুয়াল পরীক্ষা বা পর্যবেক্ষণের মাধ্যমে খুঁজে পাওয়া যায় না। প্রত্যাশার মতো আচরণ করে না এমন ফলাফলের চিত্র তুলে ধরে উদাহরণগুলির জন্য অনুসন্ধান করতে আপনাকে কিছু কোড লিখতে হতে পারে।

ধরুন আপনি নিকটতম পয়সা থেকে কিছু পেতে চান। সুতরাং আপনি আপনার চূড়ান্ত ফলাফলটি গ্রহণ করুন, 100 দ্বারা গুণিত করুন, 0.5 যোগ করুন, ছাঁটাই করুন, তারপরে পেনিগুলিতে ফিরে আসতে 100 কে ফলাফল ভাগ করুন। আপনার সঞ্চিত অভ্যন্তরীণ নম্বরটি যদি 3.46499999 হয় .... তবে 3.465 এর পরিবর্তে, আপনি 3.3 এর পরিবর্তে 3.46 পেতে যাবেন যখন আপনি সংখ্যাটি নিকটতম পয়সাতে গোল করবেন। তবে আপনার বেস 10 গণনাগুলি ইঙ্গিত দিয়েছে যে উত্তরটি অবশ্যই 3.465 হওয়া উচিত, যা স্পষ্টভাবে 3.47 এর চেয়ে বেশি হওয়া উচিত, 3.46 এর নিচে নয়। আপনি আর্থিক গণনার জন্য দ্বিগুণ ব্যবহার করলে বাস্তব জীবনে মাঝে মধ্যে এই জাতীয় জিনিসগুলি ঘটে ally এটি বিরল, তাই এটি একটি সমস্যা হিসাবে প্রায়শই নজরে আসে তবে তা ঘটে happens

যদি আপনি দ্বিগুণের পরিবর্তে আপনার অভ্যন্তরীণ গণনার জন্য বেস 10 ব্যবহার করেন তবে উত্তরগুলি সর্বদা আপনার কোডে অন্য কোনও বাগ অনুমান করে মানুষের দ্বারা প্রত্যাশিত ঠিক হয়।


2
সম্পর্কিত, আকর্ষণীয়: আমার ক্রোম জেএস কনসোলে: ম্যাথ.াউন্ড (4৯৯৯৯৯৯৯৯৯৯৯৯৯৯৯): 0 ম্যাথ.াউন্ড (4৯৯৯৯৯৯৯৯৯৯৯৯৯৯৯৯): ১
কার্টিস ইয়ালাপ

16
এই উত্তরটি বিভ্রান্তিকর। 1.40 * 165 = 231. ঠিক 231 ব্যতীত অন্য যে কোনও সংখ্যা গাণিতিক দিক থেকে ভুল (এবং অন্যান্য সমস্ত ইন্দ্রিয়) is
করু

2
@ কারু আমার মনে হয় সে কারণেই র্যান্ডি বলেছেন যে ফ্লোটগুলি খারাপ ... আমার ক্রোম জেএস কনসোল ফলাফল হিসাবে 230.99999999999997 দেখায়। যে হয় যা উত্তর তৈরি বিন্দু ভুল।
trusktr

6
@ কারু: ইমো উত্তর গাণিতিকভাবে ভুল নয়। এটি ঠিক যে এখানে 2 টি প্রশ্নের উত্তর দেওয়া হচ্ছে যা প্রশ্ন করা হচ্ছে না। আপনার সংকলকের উত্তরটির উত্তরটি 1.39999999 * 164.99999999 এবং এর ফলে গাণিতিকভাবে সঠিকভাবে 230.99999 এর সমান হয় .... স্পষ্টত থা সেই প্রশ্নটি নয় যা প্রথম স্থানে জিজ্ঞাসা করা হয়েছিল ....
মার্কস

2
@ কার্টিসওয়াল্প ডাবল ভ্যালু বন্ধ করে 0.49999999999999999 এ 0.5 হয় কেন Math.round(0.49999999999999994)1 ফেরত দেয় ?
ফুকলিভ

53

আমি এর কিছু প্রতিক্রিয়া দেখে অস্থির হয়েছি। আমি মনে করি আর্থিক গণনায় ডাবল এবং ফ্লোটের একটি জায়গা আছে। অবশ্যই, অ-ভগ্নাংশের আর্থিক পরিমাণ যুক্ত এবং বিয়োগ করার সময় পূর্ণসংখ্যা শ্রেণি বা বিগডিসিমাল ক্লাস ব্যবহার করার সময় নির্ভুলতার কোনও ক্ষতি হবে না। তবে আরও জটিল ক্রিয়াকলাপ সম্পাদন করার সময়, আপনি প্রায়শই ফলাফলগুলি শেষ করেন যা বেশ কয়েকটি বা বহু দশমিক স্থানে চলে যায়, আপনি সংখ্যাগুলি কীভাবে সংরক্ষণ করেন তা নির্বিশেষে। সমস্যাটি হল আপনি কীভাবে ফলাফল উপস্থাপন করবেন।

যদি আপনার ফলাফলটি বৃত্তাকার এবং বৃত্তাকার হয়ে যাওয়ার মধ্যে সীমান্তরেখায় থাকে এবং শেষ পয়সাটি সত্যই গুরুত্বপূর্ণ হয় তবে আপনি সম্ভবত দর্শকদের বলবেন যে উত্তরটি প্রায় মাঝখানে রয়েছে - আরও দশমিক স্থান প্রদর্শন করে।

ডাবলসের সমস্যা এবং আরও অনেক কিছু ভাসমানের ক্ষেত্রে, যখন সেগুলি বড় সংখ্যক এবং অল্প সংখ্যক একত্রিত করতে ব্যবহৃত হয়। জাভাতে,

System.out.println(1000000.0f + 1.2f - 1000000.0f);

ফলাফল স্বরূপ

1.1875

16
এই!!!! আমি এই রিলেভেন্ট ফ্যাক্টটি খুঁজতে সমস্ত উত্তর অনুসন্ধান করছিলাম! সাধারণ গণনায় আপনি যদি কিছু শতাংশের কিছুটাও না হন তবে কেউই যত্ন করে না, তবে এখানে উচ্চ সংখ্যার সাথে সহজেই প্রতি লেনদেনের জন্য কিছু ডলার হারিয়ে যায়!
ফালকো

22
এবং এখন কল্পনা করুন যে কেউ তার 1 মিলিয়ন ডলারে প্রতিদিন 0.01% উপার্জন পাচ্ছেন - তিনি প্রতিদিন কিছুই পাবেন না - এবং এক বছর পরেও তিনি 1000 ডলার অর্জন করেননি, এই উইল ম্যাটার
ফ্যালকো

6
সমস্যাটি নির্ভুলতা নয় তবে সেই ফ্লোট আপনাকে জানায় না যে এটি ভুল হয়ে গেছে। কোনও পূর্ণসংখ্যা কেবল 10 টি অঙ্ক পর্যন্ত আটকে রাখতে পারে যাতে ভাসাটি ভুল না হয়ে 6 টি ধরে রাখতে পারে (যখন আপনি সেই অনুযায়ী এটি কেটে দেবেন)। কোনও পূর্ণসংখ্যার উপচে পড়ার সময় এটি জাভির মতো ভাষা আপনাকে সতর্ক করবে বা অনুমতি দেবে না এটি এটির অনুমতি দেয়। আপনি যখন একটি ডাবল ব্যবহার করেন, আপনি 16 সংখ্যায় যেতে পারেন যা অনেকগুলি ব্যবহারের ক্ষেত্রেই যথেষ্ট।
সিগি

39

ফ্লোট এবং ডাবলগুলি আনুমানিক। আপনি যদি একটি বিগডিসিমাল তৈরি করেন এবং কনস্ট্রাক্টরের কাছে একটি ফ্লোট পাস করেন আপনি দেখতে পাবেন যে ফ্লোটটি আসলে সমান:

groovy:000> new BigDecimal(1.0F)
===> 1
groovy:000> new BigDecimal(1.01F)
===> 1.0099999904632568359375

এটি সম্ভবত আপনি কীভাবে $ 1.01 উপস্থাপন করতে চান তা নয়।

সমস্যাটি হ'ল আইইইই স্পেকের সমস্ত ভগ্নাংশকে হুবহু উপস্থাপন করার উপায় নেই, এর মধ্যে কিছুগুলি পুনরাবৃত্তি ভগ্নাংশ হিসাবে শেষ হয় যাতে আপনি আনুমানিক ত্রুটিগুলি শেষ করেন। যেহেতু হিসাবরক্ষকরা পেনির ঠিক মতো জিনিস প্রকাশ করতে পছন্দ করে এবং গ্রাহকরা যদি তাদের বিল পরিশোধ করেন এবং অর্থ প্রদানের প্রক্রিয়া শেষে তারা প্রাপ্য হন তবে তারা বিরক্ত হবেন এবং তাদের কাছ থেকে ফি নেওয়া হয় বা তাদের অ্যাকাউন্টটি বন্ধ করতে না পারলে এটি ব্যবহার করা ভাল use দশমিক (সি # তে) বা জাভা.ম্যাথ.বিগডিসিমালের মতো যথাযথ প্রকারভেদ Java

আপনি যদি গোল করেন তবে ত্রুটিটি নিয়ন্ত্রণযোগ্য নয়: পিটার লরির এই নিবন্ধটি দেখুন । প্রথম স্থানে ঘোরাঘুরি না করাই সহজ। বেশিরভাগ অ্যাপ্লিকেশন যা অর্থ পরিচালনা করে তা প্রচুর গণিতের জন্য কল করে না, অপারেশনগুলিতে জিনিসগুলি যুক্ত করা বা বিভিন্ন বালতিতে পরিমাণ বরাদ্দ করে। ভাসমান পয়েন্ট এবং গোলাকার পরিচয় করিয়ে দেওয়া কেবল বিষয়গুলিকে জটিল করে তোলে।


5
float, doubleএবং সঠিক মান BigDecimalউপস্থাপন করে । কোড টু অবজেক্ট কনভার্সেশন অপারেশন পাশাপাশি অন্যান্য ক্রিয়াকলাপ। প্রকারগুলি নিজেরাই নিখুঁত নয়।
chux - মনিকা পুনরায় ইনস্টল করুন

1
@ চাক্স: এটি পুনরায় পড়া, আমার মনে হয় আপনার একটি বক্তব্য আছে যে আমার শব্দটির উন্নতি হতে পারে। আমি এডিট করব এবং রিওয়ার্ড করব।
নাথান হিউজেস

28

আমি নিম্নমানের ঝুঁকি নিয়ে যাব, তবে আমি মনে করি মুদ্রার গণনার জন্য ভাসমান পয়েন্ট সংখ্যাগুলির অপ্রয়োজনীয়তা ওভাররেড হয়ে গেছে। যতক্ষণ আপনি জেনাক দ্বারা ব্যাখ্যা করা বাইনারি-দশমিক প্রতিনিধিত্বের অমিলটি মোকাবেলায় সঠিকভাবে সেন্ট-রাউন্ডিং করছেন এবং কাজ করার জন্য যথেষ্ট উল্লেখযোগ্য সংখ্যা রয়েছে তা নিশ্চিত করার পরেও কোনও সমস্যা হবে না।

এক্সেলে মুদ্রার সাথে গণনা করা লোকেরা সর্বদা ডাবল নির্ভুলতা ফ্লোট ব্যবহার করে থাকে (এক্সেলের কোনও মুদ্রার ধরণ নেই) এবং আমি এখনও কাউকে গোলাকার ত্রুটি সম্পর্কে অভিযোগ করতে দেখিনি।

অবশ্যই, আপনাকে কারণের মধ্যে থাকতে হবে; যেমন একটি সাধারণ ওয়েবশপ সম্ভবত ডাবল স্পষ্টতা ভাসমান নিয়ে কোনও সমস্যা অনুভব করতে পারে না, তবে আপনি যদি অ্যাকাউন্টিং বা এমন কোনও কিছু করেন যা সংখ্যার একটি বৃহত্তর (অনিয়ন্ত্রিত) সংযোজন দরকার হয়, আপনি দশ ফুট দিয়ে ভাসমান পয়েন্ট সংখ্যা স্পর্শ করতে চাইবেন না মেরু.


3
এটি আসলে একটি সুন্দর শালীন উত্তর। বেশিরভাগ ক্ষেত্রে এগুলি ব্যবহার করা পুরোপুরি ঠিক।
ওয়াহিদ আমিরি

2
এটি লক্ষ করা উচিত যে বেশিরভাগ বিনিয়োগ ব্যাংকগুলি বেশিরভাগ সি ++ প্রোগ্রামের মতো দ্বিগুণ ব্যবহার করে। কিছু দীর্ঘ ব্যবহার করে তবে ট্র্যাকিং স্কেলের নিজস্ব সমস্যা রয়েছে।
পিটার লরে

20

যদিও এটি সত্য যে ভাসমান পয়েন্টের ধরণটি কেবলমাত্র দশমিক ডেটা উপস্থাপন করতে পারে, এটিও সত্য যে কোনও একটি যদি সংখ্যাকে তাদের উপস্থাপনের আগে প্রয়োজনীয় নির্ভুলতার দিকে ঘুরিয়ে দেয় তবে সঠিক ফলাফলটি পাওয়া যায়। সাধারণত।

সাধারণত যেহেতু ডাবল টাইপটির সংক্ষিপ্ততা 16 টিরও কম। আপনার যদি আরও সঠিক নির্ভুলতার প্রয়োজন হয় তবে এটি উপযুক্ত ধরণের নয়। এছাড়াও আনুমানিক সংগ্রহ করতে পারে।

এটি অবশ্যই বলা উচিত যে আপনি নির্দিষ্ট পয়েন্ট পাটিগণিত ব্যবহার করার পরেও আপনাকে এখনও গোলাকার সংখ্যাগুলি করতে হবে, আপনি যদি পর্যায়ক্রমিক দশমিক সংখ্যা অর্জন করেন তবে বিগইন্টিজার এবং বিগডিসিমাল ত্রুটি দেয় তা কি সত্য নয়? সুতরাং এখানে একটি আনুমানিক হয়।

উদাহরণস্বরূপ, সিওবিএল, আর্থিক গণনার জন্য historতিহাসিকভাবে ব্যবহৃত, সর্বাধিক 18 পরিসংখ্যানের নির্ভুলতা রয়েছে। সুতরাং প্রায়শই একটি অন্তর্নিহিত বৃত্তাকার হয়।

উপসংহারে, আমার মতে ডাবলটি প্রায় 16 এর অঙ্কের নির্ভুলতার জন্য অনুপযুক্ত, যা অপ্রতুল হতে পারে, এটি আনুমানিক নয় বলে নয়।

পরবর্তী প্রোগ্রামের নিম্নলিখিত আউটপুটটি বিবেচনা করুন। এটি দেখায় যে ডাবল রাউন্ডিংয়ের পরে বিগডিসিমালের মতো একই ফলাফল যথাযথ 16 পর্যন্ত দেয়।

Precision 14
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.000051110111115611
Double                        : 56789.012345 / 1111111111 = 0.000051110111115611

Precision 15
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.0000511101111156110
Double                        : 56789.012345 / 1111111111 = 0.0000511101111156110

Precision 16
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.00005111011111561101
Double                        : 56789.012345 / 1111111111 = 0.00005111011111561101

Precision 17
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.000051110111115611011
Double                        : 56789.012345 / 1111111111 = 0.000051110111115611013

Precision 18
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.0000511101111156110111
Double                        : 56789.012345 / 1111111111 = 0.0000511101111156110125

Precision 19
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.00005111011111561101111
Double                        : 56789.012345 / 1111111111 = 0.00005111011111561101252

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.MathContext;

public class Exercise {
    public static void main(String[] args) throws IllegalArgumentException,
            SecurityException, IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        String amount = "56789.012345";
        String quantity = "1111111111";
        int [] precisions = new int [] {14, 15, 16, 17, 18, 19};
        for (int i = 0; i < precisions.length; i++) {
            int precision = precisions[i];
            System.out.println(String.format("Precision %d", precision));
            System.out.println("------------------------------------------------------");
            execute("BigDecimalNoRound", amount, quantity, precision);
            execute("DoubleNoRound", amount, quantity, precision);
            execute("BigDecimal", amount, quantity, precision);
            execute("Double", amount, quantity, precision);
            System.out.println();
        }
    }

    private static void execute(String test, String amount, String quantity,
            int precision) throws IllegalArgumentException, SecurityException,
            IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
        Method impl = Exercise.class.getMethod("divideUsing" + test, String.class,
                String.class, int.class);
        String price;
        try {
            price = (String) impl.invoke(null, amount, quantity, precision);
        } catch (InvocationTargetException e) {
            price = e.getTargetException().getMessage();
        }
        System.out.println(String.format("%-30s: %s / %s = %s", test, amount,
                quantity, price));
    }

    public static String divideUsingDoubleNoRound(String amount,
            String quantity, int precision) {
        // acceptance
        double amount0 = Double.parseDouble(amount);
        double quantity0 = Double.parseDouble(quantity);

        //calculation
        double price0 = amount0 / quantity0;

        // presentation
        String price = Double.toString(price0);
        return price;
    }

    public static String divideUsingDouble(String amount, String quantity,
            int precision) {
        // acceptance
        double amount0 = Double.parseDouble(amount);
        double quantity0 = Double.parseDouble(quantity);

        //calculation
        double price0 = amount0 / quantity0;

        // presentation
        MathContext precision0 = new MathContext(precision);
        String price = new BigDecimal(price0, precision0)
                .toString();
        return price;
    }

    public static String divideUsingBigDecimal(String amount, String quantity,
            int precision) {
        // acceptance
        BigDecimal amount0 = new BigDecimal(amount);
        BigDecimal quantity0 = new BigDecimal(quantity);
        MathContext precision0 = new MathContext(precision);

        //calculation
        BigDecimal price0 = amount0.divide(quantity0, precision0);

        // presentation
        String price = price0.toString();
        return price;
    }

    public static String divideUsingBigDecimalNoRound(String amount, String quantity,
            int precision) {
        // acceptance
        BigDecimal amount0 = new BigDecimal(amount);
        BigDecimal quantity0 = new BigDecimal(quantity);

        //calculation
        BigDecimal price0 = amount0.divide(quantity0);

        // presentation
        String price = price0.toString();
        return price;
    }
}

15

ভাসমান পয়েন্ট সংখ্যার ফলাফলটি সঠিক নয়, যা তাদেরকে এমন কোনও আর্থিক গণনার জন্য অনুপযুক্ত করে তোলে যার সঠিক ফলাফল প্রয়োজন এবং না প্রায় not ভাসা এবং ডাবল ইঞ্জিনিয়ারিং এবং বৈজ্ঞানিক গণনার জন্য ডিজাইন করা হয়েছে এবং অনেক সময় সঠিক ফলাফলও দেয় না ভাসমান পয়েন্ট গণনার ফলাফলও জেভিএম থেকে জেভিএমে পরিবর্তিত হতে পারে। বিগডিসিমাল এবং ডাবল আদিম এর নীচের উদাহরণটি দেখুন যা অর্থের মান উপস্থাপনের জন্য ব্যবহৃত হয়, এটি একেবারে স্পষ্ট যে ভাসমান পয়েন্ট গণনা সঠিক নাও হতে পারে এবং আর্থিক গণনার জন্য বিগডিসিমাল ব্যবহার করা উচিত।

    // floating point calculation
    final double amount1 = 2.0;
    final double amount2 = 1.1;
    System.out.println("difference between 2.0 and 1.1 using double is: " + (amount1 - amount2));

    // Use BigDecimal for financial calculation
    final BigDecimal amount3 = new BigDecimal("2.0");
    final BigDecimal amount4 = new BigDecimal("1.1");
    System.out.println("difference between 2.0 and 1.1 using BigDecimal is: " + (amount3.subtract(amount4)));

আউটপুট:

difference between 2.0 and 1.1 using double is: 0.8999999999999999
difference between 2.0 and 1.1 using BigDecimal is: 0.9

3
আসুন আমরা তুচ্ছ সংযোজন / বিয়োগ এবং পূর্ণসংখ্যক মিটপ্লিকাইটন ছাড়াও অন্য কিছু চেষ্টা করি, কোডটি যদি 7% loanণের মাসিক হার গণনা করে তবে উভয় প্রকারের সঠিক মান প্রদান করতে ব্যর্থ হতে হবে এবং নিকটবর্তী 0.01 এর গোলাকার প্রয়োজন হবে। সর্বনিম্ন আর্থিক ইউনিটকে গোল করা অর্থের গণনার একটি অংশ, দশমিক প্রকারগুলি ব্যবহার করে সংযোজন / বিয়োগের সাথে প্রয়োজনীয়তা এড়াতে হবে - তবে অন্য কিছু নয়।
chux - মনিকা

@ chux-ReinstateMonica: যদি সুদের মাসিক যৌগিক হিসাবে বিবেচনা করা হয়, তবে প্রতি মাসের সুদের পরিমাণটি দৈনিক ভারসাম্যকে একসাথে যোগ করে, 7 (সুদের হার) দিয়ে গুন করুন, এবং নিকটতম পেনির সাথে ভাগ করে দিনগুলি সংখ্যা দ্বারা ভাগ করুন বছর. একেবারে শেষ ধাপে প্রতিমাসে একবার ছাড়া আর কোথাও গোল হয় না।
সুপারক্যাট

@ সুপের্যাট আমার মন্তব্যটি সর্বনিম্ন মুদ্রা ইউনিটের একটি বাইনারি এফপি বা একটি দশমিক এফপি ব্যবহারের উপর জোর দেয় - যেমন আপনার মন্তব্যে "এবং বিভাজন, নিকটতম পেনি দিয়ে গোল করা"। বেস 2 বা বেস 10 এফপি ব্যবহার করা আপনার দৃশ্যে কোনও উপায়ে সরবরাহ করে না।
chux - মনিকা

@ chux-ReinstateMonica: উপরের দৃশ্যে, যদি গণিতটি কাজ করে যে আগ্রহটি অর্ধ-সেন্টের কয়েকটি সংখ্যার সমানভাবে হওয়া উচিত, একটি সঠিক আর্থিক প্রোগ্রাম অবশ্যই নির্দিষ্ট নির্দিষ্ট ফ্যাশনে গোল করতে হবে। যদি ভাসমান-পয়েন্ট গণনাগুলির সুদের মান যেমন $ 1.23499941 পাওয়া যায় তবে রাউন্ডিংয়ের আগে গাণিতিকভাবে-যথাযথ মানটি অবশ্যই 23 1.235 হওয়া উচিত এবং রাউন্ডিংটি "নিকটতম এমনকি" হিসাবে নির্দিষ্ট করা উচিত, যেমন ভাসমান-পয়েন্ট গণনার ব্যবহার ফলাফলের কারণ হবে না $ 0.000059 দ্বারা বন্ধ থাকুন, বরং পুরো $ 0.01 দ্বারা বন্ধ করুন, যা অ্যাকাউন্টিংয়ের উদ্দেশ্যে জাস্ট প্লেইন ভুল।
সুপারক্যাট

@ সুপের্যাট doubleশতাংশে বাইনারি এফপি ব্যবহার করে 0.5 শতাংশ হিসাবে গণনা করতে কোনও সমস্যা হবে না কারণ দশমিক এফপিও নয়। যদি ফ্লোটিং-পয়েন্ট গণনাগুলি 123.499941 eg যেমন একটি বাইনারি এফপি বা দশমিক এফপির মাধ্যমে, এর সুদের মান অর্জন করে তবে ডাবল রাউন্ডিং সমস্যাটি একই - কোনওভাবেই কোনও সুবিধা হবে না। আপনার ভিত্তিটি গাণিতিক-নির্ভুল মান ধরেছে এবং দশমিক এফপি এক হিসাবে মনে হচ্ছে - এমন কি দশমিক এফপিও গ্যারান্টি দেয় না। 0.5 / 7.0 * 7.0 বাইনারি এবং ডিকমাল এফপির ক্ষেত্রে সমস্যা। আইএসি, সিটির পরবর্তী সংস্করণটি দশমিক এফপি সরবরাহ করবে বলে আমি প্রত্যাশা করায় বেশিরভাগই মোট হবে।
chux - মনিকা পুনরায় ইনস্টল করুন

11

যেমনটি আগে বলা হয়েছিল "ডাবল বা ভাসমান হিসাবে অর্থ উপস্থাপন করা সম্ভবত সফ্টওয়্যারটির ক্ষুদ্র ত্রুটিগুলি সরিয়ে দেয় তবে আপনি যথাযথ সংখ্যায় আরও সংযোজন, বিয়োগ, গুণ এবং বিভাগগুলি সম্পাদন করার ফলে আপনি আরও এবং আরও নির্ভুলতা হারাবেন ত্রুটিগুলি যুক্ত হওয়ার সাথে সাথে এটি অর্থের সাথে লেনদেনের জন্য ভাসমান এবং দ্বিগুণ অপর্যাপ্ত করে তোলে, যেখানে বেস 10 শক্তির বহুগুণের জন্য নিখুঁত নির্ভুলতা প্রয়োজন ""

অবশেষে জাভা মুদ্রা এবং অর্থ দিয়ে কাজ করার একটি স্ট্যান্ডার্ড উপায় আছে!

জেএসআর 354: অর্থ এবং মুদ্রার এপিআই

জেএসআর 354 অর্থ এবং মুদ্রার সাথে ব্যাপক গণনা উপস্থাপন, পরিবহন এবং সম্পাদনের জন্য একটি এপিআই সরবরাহ করে। আপনি এই লিঙ্ক থেকে এটি ডাউনলোড করতে পারেন:

জেএসআর 354: অর্থ এবং মুদ্রার এপিআই ডাউনলোড করুন

স্পেসিফিকেশন নিম্নলিখিত জিনিস নিয়ে গঠিত:

  1. হ্যান্ডলিংয়ের জন্য একটি API যেমন আর্থিক পরিমাণ এবং মুদ্রা
  2. বিনিময়যোগ্য প্রয়োগগুলি সমর্থন করার জন্য API গুলি
  3. বাস্তবায়ন ক্লাসগুলির উদাহরণ তৈরির কারখানাগুলি
  4. গণনা, রূপান্তর এবং আর্থিক পরিমাণের বিন্যাসকরণের জন্য কার্যকারিতা
  5. মানি এবং মুদ্রার সাথে কাজ করার জন্য জাভা এপিআই, যা জাভা 9 এ অন্তর্ভুক্ত করার পরিকল্পনা করা হয়েছে।
  6. সমস্ত স্পেসিফিকেশন ক্লাস এবং ইন্টারফেস javax.money। * প্যাকেজে অবস্থিত।

জেএসআর 354 এর নমুনা উদাহরণ: অর্থ এবং মুদ্রার এপিআই:

মুদ্রাআমাউন্ট তৈরি করার এবং কনসোলে এটি মুদ্রণের উদাহরণটি দেখতে এরকম দেখাচ্ছে:

MonetaryAmountFactory<?> amountFactory = Monetary.getDefaultAmountFactory();
MonetaryAmount monetaryAmount = amountFactory.setCurrency(Monetary.getCurrency("EUR")).setNumber(12345.67).create();
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));

রেফারেন্স বাস্তবায়ন এপিআই ব্যবহার করার সময়, প্রয়োজনীয় কোডটি অনেক সহজ:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));

এপিআই মনিটারিঅ্যামাউন্টস সহ গণনাগুলি সমর্থন করে:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmount otherMonetaryAmount = monetaryAmount.divide(2).add(Money.of(5, "EUR"));

কারেন্সিউইনিট এবং মুদ্রাঅ্যামাউন্ট

// getting CurrencyUnits by locale
CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN);
CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);

মানিটারাউন্টে বিভিন্ন পদ্ধতি রয়েছে যা নির্ধারিত মুদ্রা, সংখ্যার পরিমাণ, তার যথার্থতা এবং আরও অনেক কিছু অ্যাক্সেসের অনুমতি দেয়:

MonetaryAmount monetaryAmount = Money.of(123.45, euro);
CurrencyUnit currency = monetaryAmount.getCurrency();
NumberValue numberValue = monetaryAmount.getNumber();

int intValue = numberValue.intValue(); // 123
double doubleValue = numberValue.doubleValue(); // 123.45
long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100
long fractionNumerator = numberValue.getAmountFractionNumerator(); // 45
int precision = numberValue.getPrecision(); // 5

// NumberValue extends java.lang.Number. 
// So we assign numberValue to a variable of type Number
Number number = numberValue;

MonetaryAmounts একটি বৃত্তাকার অপারেটর ব্যবহার করে বৃত্তাকার করা যেতে পারে:

CurrencyUnit usd = MonetaryCurrencies.getCurrency("USD");
MonetaryAmount dollars = Money.of(12.34567, usd);
MonetaryOperator roundingOperator = MonetaryRoundings.getRounding(usd);
MonetaryAmount roundedDollars = dollars.with(roundingOperator); // USD 12.35

মানিএমাউন্টগুলির সংগ্রহের সাথে কাজ করার সময়, ফিল্টারিং, বাছাই এবং গোষ্ঠীকরণের জন্য কয়েকটি দুর্দান্ত ইউটিলিটি পদ্ধতি উপলব্ধ।

List<MonetaryAmount> amounts = new ArrayList<>();
amounts.add(Money.of(2, "EUR"));
amounts.add(Money.of(42, "USD"));
amounts.add(Money.of(7, "USD"));
amounts.add(Money.of(13.37, "JPY"));
amounts.add(Money.of(18, "USD"));

কাস্টম মানিঅ্যামাউন্ট ক্রিয়াকলাপ

// A monetary operator that returns 10% of the input MonetaryAmount
// Implemented using Java 8 Lambdas
MonetaryOperator tenPercentOperator = (MonetaryAmount amount) -> {
  BigDecimal baseAmount = amount.getNumber().numberValue(BigDecimal.class);
  BigDecimal tenPercent = baseAmount.multiply(new BigDecimal("0.1"));
  return Money.of(tenPercent, amount.getCurrency());
};

MonetaryAmount dollars = Money.of(12.34567, "USD");

// apply tenPercentOperator to MonetaryAmount
MonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567

সম্পদ:

জেএসআর 354 এর সাহায্যে জাভাতে অর্থ এবং মুদ্রা পরিচালনা করা

জাভা 9 অর্থ এবং মুদ্রার এপিআই (জেএসআর 354) সন্ধান করছেন

আরও দেখুন: জেএসআর 354 - মুদ্রা এবং অর্থ


5

যদি আপনার গণনায় বিভিন্ন পদক্ষেপ জড়িত থাকে, স্বেচ্ছাচারিত নির্ভুলতা পাটিগণিত আপনাকে 100% কভার করবে না।

ফলাফলের নিখুঁত উপস্থাপনা ব্যবহারের একমাত্র নির্ভরযোগ্য উপায় (একটি কাস্টম ভগ্নাংশ ডেটা ব্যবহার করুন যা বিভাগের ক্রিয়াকে শেষ ধাপে ব্যাচ করবে) এবং কেবলমাত্র শেষ ধাপে দশমিক স্বীকৃতিতে রূপান্তরিত।

স্বেচ্ছাসেবক নির্ভুলতা সাহায্য করবে না কারণ সর্বদা এমন সংখ্যা থাকতে পারে যেখানে এতগুলি দশমিক স্থান থাকে বা কিছু ফলাফল যেমন 0.6666666... কোনও নির্বিচারে উপস্থাপনা শেষ উদাহরণটি আবরণ করে না। সুতরাং আপনার প্রতিটি পদক্ষেপে ছোট ছোট ত্রুটি থাকবে।

এই ত্রুটিগুলি অ্যাড আপ হবে, শেষ পর্যন্ত আর এড়ানো সহজ হবে না become একে ত্রুটি প্রচার বলে


4

অর্থ এবং মুদ্রার গণনার জন্য কারো দ্বিগুণ ব্যবহার করা উচিত নয় কেন তা বেশিরভাগ উত্তরে হাইলাইট করেছে। এবং আমি তাদের সাথে সম্পূর্ণ একমত

যদিও এর অর্থ এই নয় যে ডাবলগুলি কখনই সেই উদ্দেশ্যে ব্যবহার করা যায় না।

আমি খুব কম জিসি প্রয়োজনীয়তা সহ বেশ কয়েকটি প্রকল্পে কাজ করেছি এবং বিগডিসিমাল অবজেক্টগুলি সেই ওভারহেডে বড় অবদানকারী ছিল।

এটি দ্বিগুণ প্রতিনিধিত্ব সম্পর্কে বোঝার অভাব এবং যথাযথতা এবং নির্ভুলতা পরিচালনা করার অভিজ্ঞতার অভাব যা এই বিজ্ঞ পরামর্শটি নিয়ে আসে।

আপনি যদি আপনার প্রকল্পের যথাযথতা এবং নির্ভুলতার প্রয়োজনীয়তাগুলি পরিচালনা করতে সক্ষম হন তবে আপনি এটি কার্যকর করতে পারেন, যা দ্বিগুণ মানের পরিসীমা নিয়ে কাজ করে তার উপর ভিত্তি করে সম্পন্ন করতে হয়।

আপনি আরও ধারণা পেতে পেয়ারার ফাজি কম্পিউটার পদ্ধতিটি দেখুন। প্যারামিটার সহনশীলতা মূল। সিকিওরিটি ট্রেডিং অ্যাপ্লিকেশনের জন্য আমরা এই সমস্যাটি মোকাবিলা করেছি এবং আমরা বিভিন্ন পরিসরে বিভিন্ন সংখ্যাগত মানগুলির জন্য কী ব্যবহার সহ্য করতে পারে সে সম্পর্কে একটি বিস্তৃত গবেষণা করেছি।

এছাড়াও, এমন পরিস্থিতিতে থাকতে পারে যখন আপনি হ্যাশ ম্যাপের বাস্তবায়ন হিসাবে মানচিত্র কী হিসাবে ডাবল মোড়ক ব্যবহার করতে প্ররোচিত হন। এটি অত্যন্ত ঝুঁকিপূর্ণ কারণ ডাবল.এক্কালস এবং হ্যাশ কোড উদাহরণস্বরূপ "0.5" এবং "0.6 - 0.1" মানসিক চাপ সৃষ্টি করবে।


2

এই প্রশ্নের পোস্ট করা অনেক উত্তর আইইইই এবং ভাসমান-পয়েন্ট পাটিগণিতের চারপাশের মানদণ্ডগুলি নিয়ে আলোচনা করে।

একটি কম্পিউটারবিহীন বিজ্ঞান পটভূমি (পদার্থবিজ্ঞান এবং প্রকৌশল) থেকে এসে আমি সমস্যাগুলিকে অন্য দৃষ্টিকোণ থেকে দেখার প্রবণতা করি। আমার জন্য, যে কারণে আমি গাণিতিক গণনায় ডাবল বা ভাসমান ব্যবহার করব না তা হ'ল আমি খুব বেশি তথ্য হারাব।

বিকল্পগুলি কি? এখানে অনেকগুলি (এবং আরও অনেক কিছুই আমি অবগত নই!)।

জাভাতে বিগডিসিমাল জাভা ভাষার স্থানীয়। অ্যাপফ্লোট জাভা-র জন্য আরেকটি নির্বিচার-যথার্থ গ্রন্থাগার।

সি # তে দশমিক ডেটা টাইপ হ'ল 28 টি গুরুত্বপূর্ণ ব্যক্তির জন্য মাইক্রোসফ্টের .NET বিকল্প।

SciPy (বৈজ্ঞানিক পাইথন) সম্ভবত আর্থিক গণনাও পরিচালনা করতে পারে (আমি চেষ্টা করি নি, তবে আমার সন্দেহ হয়)।

জিএনইউ মাল্টিপল প্রিসিন লাইব্রেরি (জিএমপি) এবং জিএনইউ এমএফপিআর লাইব্রেরি সি এবং সি ++ এর জন্য দুটি ফ্রি এবং ওপেন-সোর্স রিসোর্স।

জাভাস্ক্রিপ্ট (!) এর জন্য সংখ্যাগত নির্ভুলতা গ্রন্থাগারগুলিও রয়েছে এবং আমি মনে করি পিএইচপি যা আর্থিক গণনা পরিচালনা করতে পারে।

মালিকানাধীন (বিশেষত, আমি মনে করি, ফরট্রানের জন্য) এবং অনেকগুলি কম্পিউটার ভাষার জন্য ওপেন-সোর্স সমাধানও রয়েছে।

প্রশিক্ষণ নিয়ে আমি কম্পিউটার বিজ্ঞানী নই। যাইহোক, আমি জাভাতে বিগডিসিমাল বা সি # তে দশমিকের দিকে ঝুঁকতে চাই। আমি তালিকাভুক্ত অন্যান্য সমাধানগুলি চেষ্টা করে দেখিনি, তবে সেগুলি সম্ভবত খুব ভাল।

আমার জন্য, আমি বিগডিসিমাল পছন্দ করি কারণ এটি যে পদ্ধতিগুলি সমর্থন করে। সি # এর দশমিকটি খুব সুন্দর, তবে আমি যতটা চাই তার সাথে কাজ করার সুযোগ পাইনি। আমি আমার অতিরিক্ত সময়টিতে আমার কাছে আগ্রহের বৈজ্ঞানিক গণনা করি এবং বিগডিসিমাল খুব ভালভাবে কাজ করে বলে মনে হয় কারণ আমি আমার ভাসমান পয়েন্ট সংখ্যাগুলির যথার্থতা নির্ধারণ করতে পারি। বিগডিসিমালের অসুবিধা? এটি সময়ে সময়ে ধীর হতে পারে, বিশেষত যদি আপনি বিভাজন পদ্ধতিটি ব্যবহার করেন।

আপনি, গতির জন্য, সি, সি ++ এবং ফোর্টরানের বিনামূল্যে এবং মালিকানাধীন গ্রন্থাগারগুলি সন্ধান করতে পারেন।


1
সায়পিপি / নম্পি সম্পর্কিত, স্থির-নির্ভুলতা (অর্থাত্ পাইথনের দশমিক ec ডেসিমাল) সমর্থিত নয় ( ডকস.সসিপি.আর / ডক / নম্পি- দেব / ব্যবহারকারী / বেসিকস.টি.এসপিটিএমএল )। কিছু ফাংশন দশমিকের সাথে সঠিকভাবে কাজ করবে না (উদাহরণস্বরূপ ইসসান)। পান্ডস নিম্পির উপর ভিত্তি করে এবং একেিউআর-তে শুরু করা হয়েছিল, এটি একটি প্রধান পরিমাণগত হেজ-তহবিল। সুতরাং আর্থিক গণনা (মুদি অ্যাকাউন্টিং নয়) সম্পর্কিত আপনার উত্তর রয়েছে answer
কমটেট

2

পূর্ববর্তী উত্তরগুলি যুক্ত করার জন্য, জোদা-মানি প্রয়োগের বিকল্পও রয়েছে প্রশ্নে সম্বোধন করা সমস্যাটি মোকাবেলা করার সময় বিগডেসিমাল ছাড়াও জাভাতে । জাভা মডুলের নাম org.joda.money।

এটি জাভা এসই 8 বা তার পরে প্রয়োজন এবং এর কোনও নির্ভরতা নেই।

আরও সুনির্দিষ্টভাবে বলতে গেলে, সংকলন-সময় নির্ভরতা রয়েছে তবে এটির প্রয়োজন নেই।

<dependency>
  <groupId>org.joda</groupId>
  <artifactId>joda-money</artifactId>
  <version>1.0.1</version>
</dependency>

জোদা মানি ব্যবহারের উদাহরণ:

  // create a monetary value
  Money money = Money.parse("USD 23.87");

  // add another amount with safe double conversion
  CurrencyUnit usd = CurrencyUnit.of("USD");
  money = money.plus(Money.of(usd, 12.43d));

  // subtracts an amount in dollars
  money = money.minusMajor(2);

  // multiplies by 3.5 with rounding
  money = money.multipliedBy(3.5d, RoundingMode.DOWN);

  // compare two amounts
  boolean bigAmount = money.isGreaterThan(dailyWage);

  // convert to GBP using a supplied rate
  BigDecimal conversionRate = ...;  // obtained from code outside Joda-Money
  Money moneyGBP = money.convertedTo(CurrencyUnit.GBP, conversionRate, RoundingMode.HALF_UP);

  // use a BigMoney for more complex calculations where scale matters
  BigMoney moneyCalc = money.toBigMoney();

ডকুমেন্টেশন: http://joda-money.sourceforge.net/apidocs/org/joda/money/Money.html

বাস্তবায়ন উদাহরণগুলি: https://www.programcreek.com/java-api-example/?api=org.joda.money.Money


0

কিছু উদাহরণ ... এটি প্রায় কোনও প্রোগ্রামিং ভাষার ক্ষেত্রে (আসলে প্রত্যাশার মতো কাজ করে না) কাজ করে ... আমি ডেলফি, ভিবিএস স্ক্রিপ্ট, ভিজ্যুয়াল বেসিক, জাভাস্ক্রিপ্ট এবং এখন জাভা / অ্যান্ড্রয়েড দিয়ে চেষ্টা করেছি:

    double total = 0.0;

    // do 10 adds of 10 cents
    for (int i = 0; i < 10; i++) {
        total += 0.1;  // adds 10 cents
    }

    Log.d("round problems?", "current total: " + total);

    // looks like total equals to 1.0, don't?

    // now, do reverse
    for (int i = 0; i < 10; i++) {
        total -= 0.1;  // removes 10 cents
    }

    // looks like total equals to 0.0, don't?
    Log.d("round problems?", "current total: " + total);
    if (total == 0.0) {
        Log.d("round problems?", "is total equal to ZERO? YES, of course!!");
    } else {
        Log.d("round problems?", "is total equal to ZERO? NO... thats why you should not use Double for some math!!!");
    }

আউটপুট:

round problems?: current total: 0.9999999999999999 round problems?: current total: 2.7755575615628914E-17 round problems?: is total equal to ZERO? NO... thats why you should not use Double for some math!!!


3
সমস্যাটি এমন নয় যে রাউন্ড-অফ ত্রুটি ঘটে, তবে আপনি এটি মোকাবেলা করেন না। ফলটিকে দুটি দশমিক স্থানে গোল করুন (যদি আপনি সেন্ট চান) এবং আপনার কাজ শেষ।
মার্টিনাস

0

বিভিন্ন নকশার সাথে ভাসাটি দশমিকের বাইনারি রূপ; তারা দুটি ভিন্ন জিনিস. একে অপরের সাথে রূপান্তরিত হওয়ার সময় দুটি ধরণের মধ্যে অল্প ত্রুটি রয়েছে। এছাড়াও, ভাসমানটি বৈজ্ঞানিক জন্য অসীম সংখ্যক মান উপস্থাপনের জন্য ডিজাইন করা হয়েছে। এর অর্থ এটি নির্দিষ্ট সংখ্যক বাইটের সাথে চূড়ান্ত ছোট এবং চরম সংখ্যক সংখ্যক স্পষ্টতা হারিয়ে যাওয়ার জন্য ডিজাইন করা হয়েছে। দশমিক হ'ল অসীম মানগুলির প্রতিনিধিত্ব করতে পারে না, এটি কেবলমাত্র দশমিক অঙ্কের সংখ্যায় সীমাবদ্ধ। সুতরাং ফ্লোট এবং ডেসিমাল বিভিন্ন উদ্দেশ্যে।

মুদ্রা মানটির জন্য ত্রুটিটি পরিচালনা করার কিছু উপায় রয়েছে:

  1. পরিবর্তে দীর্ঘ পূর্ণসংখ্যা এবং সেন্টগুলিতে গণনা করুন।

  2. দ্বিগুণ নির্ভুলতা ব্যবহার করুন, আপনার উল্লেখযোগ্য সংখ্যাগুলি কেবল 15 এ রাখুন যাতে দশমিকটি হুবহু অনুকরণ করা যায়। মান উপস্থাপনের আগে গোল; গণনা করার সময় প্রায়শই গোল হয়।

  3. জাভা বিগডিসিমালের মতো দশমিক লাইব্রেরি ব্যবহার করুন যাতে দশমিকের অনুকরণের জন্য আপনার দ্বিগুণ ব্যবহারের প্রয়োজন হবে না।

PS এটি জেনে রাখা আকর্ষণীয় যে বেশিরভাগ ব্র্যান্ডের হ্যান্ডহেল্ড বৈজ্ঞানিক ক্যালকুলেটরগুলি ফ্লোটের পরিবর্তে দশমিকের উপরে কাজ করে। সুতরাং কারও অভিযোগ রূপান্তর ত্রুটি ভাসাচ্ছে না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.