জাভাস্ক্রিপ্টে সুনির্দিষ্ট আর্থিক গণনা। গোটচা কি?


125

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

উত্তর:


107

আপনার দশমিক মানগুলি সম্ভবত 100 দ্বারা স্কেল করা উচিত এবং পুরো সেন্টগুলিতে সমস্ত আর্থিক মান উপস্থাপন করুন। এটি ভাসমান-পয়েন্ট যুক্তি এবং পাটিগণিতের সমস্যাগুলি এড়ানোর জন্য । জাভাস্ক্রিপ্টে কোনও দশমিক তথ্য প্রকার নেই - একমাত্র সংখ্যাগত ডেটা টাইপ হ'ল ভাসমান-পয়েন্ট। সুতরাং সাধারণত ডলারের 2550পরিবর্তে সেন্ট হিসাবে অর্থ পরিচালনা করার পরামর্শ দেওয়া হয় 25.50

জাভাস্ক্রিপ্ট এ বিবেচনা করুন:

var result = 1.0 + 2.0;     // (result === 3.0) returns true

কিন্তু:

var result = 0.1 + 0.2;     // (result === 0.3) returns false

এক্সপ্রেশনটি 0.1 + 0.2 === 0.3প্রত্যাবর্তন করে falseতবে ভাগ্যক্রমে ভাসমান-বিন্দুতে পূর্ণসংখ্যার গাণিতিকটি সঠিক, সুতরাং দশমিক প্রতিনিধিত্ব ত্রুটি 1 টি স্কেল করে এড়ানো যেতে পারে ।

মনে রাখবেন যে প্রকৃত সংখ্যার সেটটি অসীম হলেও, কেবলমাত্র তাদের মধ্যে একটি সীমাবদ্ধ সংখ্যা (18,437,736,874,454,810,627 যথাযথ হতে) জাভাস্ক্রিপ্টের ভাসমান-পয়েন্ট ফর্ম্যাটের দ্বারা ঠিক উপস্থাপন করা যেতে পারে। অতএব অন্যান্য সংখ্যার উপস্থাপনাটি আসল সংখ্যা 2 এর একটি অনুমান হিসাবে হবে ।


1 ডগলাস ক্রকফোর্ড: জাভাস্ক্রিপ্ট: ভাল পার্টস : পরিশিষ্ট এ - ভয়ঙ্কর যন্ত্রাংশ (পৃষ্ঠা 105)
2 ডেভিড ফ্লানাগান: জাভাস্ক্রিপ্ট: সংজ্ঞা নির্দেশিকা, চতুর্থ সংস্করণ : 3.1.3 ভাসমান-পয়েন্ট লিটারালস (পৃষ্ঠা 31)


3
এবং একটি অনুস্মারক হিসাবে, সর্বদা শতকরা হিসাবে গণনাগুলি, এবং গ্রাহকের পক্ষে সর্বনিম্ন উপকারী উপায়ে এটি করুন, IE আপনি যদি ট্যাক্স গণনা করে থাকেন তবে গোল করুন। আপনি যদি উপার্জিত সুদের গণনা করছেন, ছাঁটাই করুন।
জোশ

6
@Cirrostratus: আপনি চেক করতে পারেন stackoverflow.com/questions/744099 । আপনি যদি স্কেলিং পদ্ধতিটি নিয়ে এগিয়ে যান তবে সাধারণভাবে আপনি যথাযথতা ধরে রাখতে চান এমন দশমিক সংখ্যা দ্বারা আপনার মানটি স্কেল করতে চান। আপনার যদি 2 দশমিক স্থানের প্রয়োজন হয়, 100 দ্বারা স্কেল করুন, আপনার 4 টির প্রয়োজন হয়, 10000 দ্বারা স্কেল করুন
ড্যানিয়েল ভ্যাসালো

2
... 3000.57 মান সম্পর্কিত, হ্যাঁ, আপনি যদি জাভাস্ক্রিপ্ট ভেরিয়েবলগুলিতে সেই মানটি সংরক্ষণ করেন এবং আপনি এটিতে পাটিগণিত করতে চান, আপনি এটি 300057 (সেন্টের সংখ্যা) আকারে সঞ্চয় করতে চাইতে পারেন। কারণ 3000.57 + 0.11 === 3000.68রিটার্ন false
ড্যানিয়েল ভ্যাসালো

7
ডলারের পরিবর্তে পেনিস গণনা করলে কোনও লাভ হবে না। পেনিগুলি গণনা করার সময়, আপনি প্রায় 10 ^ 16 এ পূর্ণসংখ্যায় 1 যুক্ত করার ক্ষমতাটি ছেড়ে দেন। ডলার গণনা করার সময় আপনি 10 ^ 14 এ একটি সংখ্যায় .01 যুক্ত করার ক্ষমতা হারাবেন। এটি উভয় উপায়ে একই।
slashingweapon

1
আমি সবেমাত্র একটি এনএমপি এবং বওয়ার মডিউল তৈরি করেছি যা আশা করি এই কাজের সাথে সহায়তা করবে!
পেনসিয়ারইনমোজিকা

18

প্রতিটি মান 100 দ্বারা স্কেল করা সমাধান। এটি হাতে হাতে করা সম্ভবত অকেজো, যেহেতু আপনি এমন লাইব্রেরি খুঁজে পেতে পারেন যা আপনার পক্ষে এটি করে। আমি মনিসেফের প্রস্তাব দিচ্ছি, যা ES6 অ্যাপ্লিকেশনগুলির জন্য উপযুক্ত একটি কার্যকরী এপিআই সরবরাহ করে:

const { in$, $ } = require('moneysafe');
console.log(in$($(10.5) + $(.3)); // 10.8

https://github.com/ericelliott/moneysafe

নোড.জে এবং ব্রাউজার উভয় ক্ষেত্রেই কাজ করে।


2
সম্মত। "স্কেল বাই 100" পয়েন্টটি ইতিমধ্যে স্বীকৃত উত্তরে isাকা রয়েছে, তবে আপনি আধুনিক জাভাস্ক্রিপ্ট সিনট্যাক্স সহ একটি সফ্টওয়্যার প্যাকেজ বিকল্প যুক্ত করেছেন তা ভাল। FWIW in$, $ এর আগে যে প্যাকেজটি ব্যবহার করে নি তার নামগুলির নাম অস্পষ্ট। আমি জানি যে জিনিসগুলির নামকরণ করা এরিকের পছন্দ ছিল, তবে আমি এখনও মনে করি এটি যথেষ্ট পরিমাণে ভুল ছিল যে আমি সম্ভবত তাদের নামকরণ করে আমদানি / কাঠামোগত বিবৃতি প্রয়োজন।
james_womack

4
100 দ্বারা স্কেলিং কেবলমাত্র তখনই সহায়তা করে যতক্ষণ না আপনি শতাংশ গণনা (ডিভিশন সম্পাদন করুন, মূলত) এর মতো কিছু করতে শুরু করেন।
পয়েন্টি

2
আমি আশা করি আমি একাধিকবার একটি মন্তব্য upvote করতে পারেন। 100 দ্বারা স্কেলিং যথেষ্ট নয়। জাভাস্ক্রিপ্টের একমাত্র সংখ্যাগত ডেটাটাইপটি এখনও একটি ভাসমান পয়েন্টের ডেটা টাইপ এবং আপনি এখনও উল্লেখযোগ্য বৃত্তাকার ত্রুটিগুলি সহ শেষ করতে চলেছেন।
ক্রেগ

1
আর রিডমি থেকে অন্য মাথা: Money$afe has not yet been tested in production at scale.। কেবল এটি নির্দেশ করে যাতে যে কেউ তাদের ব্যবহারের ক্ষেত্রে এটি উপযুক্ত কিনা তা বিবেচনা করতে পারে
নোবিটা

7

মাত্র দুটি দশমিক ভগ্নাংশের সংখ্যার কারণে "সুনির্দিষ্ট" আর্থিক গণনার মতো কিছুই নেই তবে এটি আরও সাধারণ সমস্যা।

জাভাস্ক্রিপ্টে, আপনি প্রতিটি মান 100 দ্বারা স্কেল করতে এবং ব্যবহার করতে পারেন Math.round() কোনও ভগ্নাংশ দেখা দিতে পারে তা ব্যবহার করুন।

আপনি নম্বর সংরক্ষণ করতে কোনও অবজেক্ট ব্যবহার করতে পারেন এবং এর প্রোটোটাইপ valueOf()পদ্ধতিতে গোলটি অন্তর্ভুক্ত করতে পারেন । এটার মত:

sys = require('sys');

var Money = function(amount) {
        this.amount = amount;
    }
Money.prototype.valueOf = function() {
    return Math.round(this.amount*100)/100;
}

var m = new Money(50.42355446);
var n = new Money(30.342141);

sys.puts(m.amount + n.amount); //80.76569546
sys.puts(m+n); //80.76

এই উপায়ে, আপনি যতবার মানি-অবজেক্ট ব্যবহার করবেন, এটি দুটি দশমিক হিসাবে গোল হিসাবে উপস্থাপিত হবে। সীমাহীন মানটির মাধ্যমে এখনও অ্যাক্সেসযোগ্য m.amount

আপনি Money.prototype.valueOf()যদি চান তবে আপনি নিজের বৃত্তাকার অ্যালগরিদম এ তৈরি করতে পারেন।


আমি এই অবজেক্ট-ভিত্তিক পদ্ধতির পছন্দ করি, মানি অবজেক্ট উভয় মান ধরে রাখে এ বিষয়টি খুব কার্যকর। এটি আমার কাস্টম অবজেক্টিভ-সি ক্লাসে তৈরি করতে আমার সঠিক ধরণের কার্যকারিতা।
জেমস_উম্যাক

4
এটি গোল করার পক্ষে যথেষ্ট সঠিক নয়।
হেনরি তাসেং

3
Sys.puts (m + n) করা উচিত নয়; //80.76 আসলে sys.puts (এম + এন) পড়ুন; //80.77? আমি বিশ্বাস করি আপনি .5 টি গোল করতে ভুলে গেছেন।
ডেভ এল

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

2
এখানে সমস্যাটি হ'ল উদাহরণস্বরূপ Money(0.1)জাভাস্ক্রিপ্ট লেক্সার উত্সটি থেকে "0.1" স্ট্রিং পড়েন এবং তারপরে এটি একটি বাইনারি ভাসমান বিন্দুতে রূপান্তর করেন এবং তারপরে আপনি ইতিমধ্যে একটি অনিচ্ছাকৃত বৃত্তাকারটি করেছেন। সমস্যাটি প্রতিনিধিত্ব সম্পর্কে (বাইনারি বনাম দশমিক) স্পষ্টতা সম্পর্কে নয় ।
এমজিডি

3

ডেসিমালজ ব্যবহার করুন ... এটি একটি খুব ভাল গ্রন্থাগার যা সমস্যার একটি কঠোর অংশ সমাধান করে ...

এটি আপনার সমস্ত ক্রিয়াকলাপে ব্যবহার করুন।

https://github.com/MikeMcl/decimal.js/


2

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

সমাধান নীচে, একটি ব্যাখ্যা নিম্নলিখিত:

এটি বুঝতে আপনার পিছনে গণিত সম্পর্কে ভাবতে হবে। 1/3 এর মতো আসল সংখ্যাগুলি দশমিক মানগুলির সাথে অঙ্কের প্রতিনিধিত্ব করা যায় না কারণ তারা অন্তহীন (যেমন - .333333333333333 ...)। দশমিকের কয়েকটি নম্বর সঠিকভাবে বাইনারিতে উপস্থাপন করা যায় না। উদাহরণস্বরূপ, ০.১ সংখ্যা সীমিত সংখ্যার সাথে সঠিকভাবে বাইনারি উপস্থাপন করা যায় না।

আরও বিশদ বিবরণের জন্য এখানে দেখুন: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

সমাধানের প্রয়োগটি একবার দেখুন: http://floating-Point-gui.de/languages/ javascript/


1

তাদের এনকোডিংয়ের বাইনারি প্রকৃতির কারণে কিছু দশমিক সংখ্যা নিখুঁত নির্ভুলতার সাথে উপস্থাপন করা যায় না। উদাহরণ স্বরূপ

var money = 600.90;
var price = 200.30;
var total = price * 3;

// Outputs: false
console.log(money >= total);

// Outputs: 600.9000000000001
console.log(total);

আপনার যদি খাঁটি জাভাস্ক্রিপ্ট ব্যবহার করতে হয় তবে আপনাকে প্রতিটি গণনার সমাধান সম্পর্কে ভাবতে হবে। উপরের কোডের জন্য আমরা দশমিকগুলি পুরো সংখ্যায় রূপান্তর করতে পারি।

var money = 60090;
var price = 20030;
var total = price * 3;

// Outputs: true
console.log(money >= total);

// Outputs: 60090
console.log(total);

জাভাস্ক্রিপ্টে দশমিক ম্যাথ নিয়ে সমস্যা এড়ানো

দুর্দান্ত ডকুমেন্টেশন সহ আর্থিক গণনার জন্য একটি নিবেদিত গ্রন্থাগার রয়েছে। Finance.js



0

দুর্ভাগ্যক্রমে এখনও পর্যন্ত সমস্ত উত্তর এ সত্যটিকে উপেক্ষা করে যে সমস্ত মুদ্রার 100 টি উপ-ইউনিট নেই (উদাঃ, শতাংশটি মার্কিন ডলারের সাব-ইউনিট (মার্কিন ডলার))। ইরাকি দিনার (আইকিউডি) এর মতো মুদ্রার 1000 টি উপ-ইউনিট রয়েছে: একটি ইরাকি দিনার 1000 টি ফাইল রয়েছে। জাপানি ইয়েন (জেপিওয়াই) এর কোনও উপ-ইউনিট নেই। সুতরাং "পূর্ণসংখ্যার গাণিতিক করতে 100 দ্বারা গুণ করুন" সর্বদা সঠিক উত্তর হয় না।

অতিরিক্ত আর্থিক হিসাবের জন্য আপনারও মুদ্রার ট্র্যাক রাখতে হবে। আপনি কোনও ভারতীয় ডলার (মার্কিন ডলার) কোনও ভারতীয় রুপিতে (আইএনআর) যুক্ত করতে পারবেন না (প্রথমে অন্যটিতে রূপান্তর না করে)।

জাভা স্ক্রিপ্টের পূর্ণসংখ্যা ডেটা ধরণের দ্বারা প্রতিনিধিত্ব করা যায় এমন সর্বোচ্চ পরিমাণেরও সীমাবদ্ধতা রয়েছে।

আর্থিক গণনাগুলিতে আপনাকে এও মাথায় রাখতে হবে যে অর্থের সীমাবদ্ধ নির্ভুলতা রয়েছে (সাধারণত 0-3 দশমিক পয়েন্ট) এবং নির্দিষ্ট পদ্ধতিতে রাউন্ডিং করা প্রয়োজন (উদাহরণস্বরূপ, "সাধারণ" রাউন্ডিং বনাম ব্যাঙ্কারের গোলাকার)) সঞ্চালনের জন্য রাউন্ডিংয়ের ধরণটি এখতিয়ার / মুদ্রার দ্বারাও পৃথক হতে পারে।

জাভাস্ক্রিপ্টে কীভাবে অর্থ পরিচালনা করবেন তা সম্পর্কিত পয়েন্টগুলির একটি খুব ভাল আলোচনা রয়েছে।

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

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