আমি কীভাবে একটি ভাসমানের মানকে (যেমন 37.777779) দুটি দশমিক স্থানে (37.78) সি এর মধ্যে গোল করতে পারি?
আমি কীভাবে একটি ভাসমানের মানকে (যেমন 37.777779) দুটি দশমিক স্থানে (37.78) সি এর মধ্যে গোল করতে পারি?
উত্তর:
যদি আপনি কেবল আউটপুট উদ্দেশ্যে সংখ্যার বৃত্তাকার করতে চান তবে "%.2f"
ফর্ম্যাট স্ট্রিংটি সত্যই সঠিক উত্তর। তবে, যদি আপনি প্রকৃতপক্ষে আরও গণনার জন্য ভাসমান বিন্দুটির মানটি গোল করতে চান তবে নীচের মতো কিছু:
#include <math.h>
float val = 37.777779;
float rounded_down = floorf(val * 100) / 100; /* Result: 37.77 */
float nearest = roundf(val * 100) / 100; /* Result: 37.78 */
float rounded_up = ceilf(val * 100) / 100; /* Result: 37.78 */
লক্ষ্য করুন যে আপনি বেছে নিতে পারেন যে তিনটি পৃথক রাউন্ডিং বিধি রয়েছে: বৃত্তাকার ডাউন (অর্থাত্, দুটি দশমিক স্থান পরে কাটা), কাছাকাছি থেকে গোলাকার, এবং রাউন্ড আপ। সাধারণত, আপনি কাছাকাছি থেকে কাছাকাছি চান।
অন্য কয়েকজন যেমন উল্লেখ করেছেন যে, ভাসমান পয়েন্ট উপস্থাপনের ছড়াছড়িগুলির কারণে, এই বৃত্তাকার মানগুলি সম্ভবত "সুস্পষ্ট" দশমিক মান নাও হতে পারে তবে তারা খুব নিকটেই থাকবে।
রাউন্ডিং সম্পর্কে অনেক বেশি (অনেক!) আরও তথ্যের জন্য, এবং বিশেষত নিকটতমকে গোল করার জন্য টাই-ব্রেকিং বিধি সম্পর্কে, রাউন্ডিং সম্পর্কিত উইকিপিডিয়া নিবন্ধটি দেখুন ।
doubles
কোনওভাবে এই কাজটি করতে পারি ? কাজ করার আমি চাই :( (ব্যবহার বলে মনে হচ্ছে না floor
এবং ceil
)।
প্রিন্টেফ । % এফ ব্যবহার করে । এটি কেবলমাত্র 2 দশমিক পয়েন্ট মুদ্রণ করে।
উদাহরণ:
printf("%.2f", 37.777779);
আউটপুট:
37.77
float
পরিসীমা হ্রাস করার সুবিধা রয়েছে val * 100
।
ধরে নিই যে আপনি মুদ্রণের মানটির চারপাশে কথা বলছেন, তারপরে অ্যান্ড্রু কোলসন এবং আরকের উত্তর সঠিক:
printf("%.2f", 37.777779);
তবে মনে রাখবেন যে আপনি যদি অভ্যন্তরীণ ব্যবহারের জন্য সংখ্যাটি ঠিক ৩ 37. to78 তে গোল করার লক্ষ্য রাখছেন (উদাহরণস্বরূপ অন্য মানের সাথে তুলনা করা) তবে ভাসমান পয়েন্ট সংখ্যাগুলি কাজ করার কারণে এটি ভাল ধারণা নয়: আপনি সাধারণত না ভাসমান পয়েন্টের জন্য সমতা তুলনা করতে চাই, পরিবর্তে একটি লক্ষ্য মান +/- একটি সিগমা মান ব্যবহার করুন। বা একটি পরিচিত নির্ভুলতার সাথে স্ট্রিং হিসাবে নম্বরটি এনকোড করুন এবং এটি তুলনা করুন।
সম্পর্কিত প্রশ্নটির গ্রেগ হিউগিলের উত্তরের লিঙ্কটি দেখুন , যা আপনাকে আর্থিক গণনার জন্য ভাসমান পয়েন্ট কেন ব্যবহার করবেন না তাও অন্তর্ভুক্ত করে।
printf("%.*f", (int)precision, (double)number);
এটি সম্পর্কে:
float value = 37.777779;
float rounded = ((int)(value * 100 + .5) / 100.0);
printf("%.2f", 37.777779);
আপনি যদি সি-স্ট্রিংয়ে লিখতে চান:
char number[24]; // dummy size, you should take care of the size!
sprintf(number, "%.2f", 37.777779);
float
অন্যকে গোল করার কোনও উপায় নেই float
কারণ গোলাকারটি float
উপস্থাপনযোগ্য নাও হতে পারে (ভাসমান-পয়েন্ট সংখ্যাগুলির সীমাবদ্ধতা)। উদাহরণস্বরূপ, আপনি 37.777779 থেকে 37.78 গোল করে বলুন তবে নিকটতম প্রতিনিধিত্বযোগ্য সংখ্যা 37.781।
তবে, আপনি একটি ফর্ম্যাট স্ট্রিং ফাংশন ব্যবহার করে "বৃত্তাকার" করতে পারেনfloat
।
float
থেকে দশমিক দশমিক জায়গায় গোল করতে পারবেন না এবং তারপরে ফলাফলটি সর্বদা n দশমিক স্থানের আশা করতে পারেন। আপনি এখনও একটি পাবেন float
, আপনি যেটি প্রত্যাশা করেছিলেন তা নয় not
এছাড়াও, আপনি যদি সি ++ ব্যবহার করেন তবে আপনি ঠিক এর মতো একটি ফাংশন তৈরি করতে পারেন:
string prd(const double x, const int decDigits) {
stringstream ss;
ss << fixed;
ss.precision(decDigits); // set # places after decimal
ss << x;
return ss.str();
}
এর পরে আপনি কোড সহ দশমিক পয়েন্টের পরে স্থানগুলির myDouble
সাথে যে কোনও দ্বিগুণ আউটপুট করতে পারেন n
:
std::cout << prd(myDouble,n);
আপনি এখনও ব্যবহার করতে পারেন:
float ceilf(float x); // don't forget #include <math.h> and link with -lm.
উদাহরণ:
float valueToRound = 37.777779;
float roundedValue = ceilf(valueToRound * 100) / 100;
সি ++ এ (বা সি-স্টাইলের ক্যাসেট সহ সিতে), আপনি ফাংশনটি তৈরি করতে পারেন:
/* Function to control # of decimal places to be output for x */
double showDecimals(const double& x, const int& numDecimals) {
int y=x;
double z=x-y;
double m=pow(10,numDecimals);
double q=z*m;
double r=round(q);
return static_cast<double>(y)+(1.0/m)*r;
}
তারপরে std::cout << showDecimals(37.777779,2);
উত্পাদন হবে: 37.78।
স্পষ্টতই আপনাকে সেই ফাংশনে সমস্ত 5 টি ভেরিয়েবল তৈরি করার দরকার নেই, তবে আমি সেগুলি সেখানে রেখেছি যাতে আপনি যুক্তি দেখতে পারেন। সম্ভবত আরও সহজ সমাধান রয়েছে, তবে এটি আমার পক্ষে ভাল কাজ করে - বিশেষত যেহেতু এটি আমার প্রয়োজন হিসাবে দশমিক জায়গার পরে অঙ্কের সংখ্যা সামঞ্জস্য করতে দেয়।
সর্বদা printf
এই জন্য ফাংশন পরিবার ব্যবহার করুন । এমনকি যদি আপনি ভাসমান হিসাবে মান পেতে চান, আপনি snprintf
স্ট্রিং হিসাবে বৃত্তাকার মান পেতে এবং তারপরে এটিকে আবার বিশ্লেষণ করে সেরা ব্যবহার করুন atof
:
#include <math.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
double dround(double val, int dp) {
int charsNeeded = 1 + snprintf(NULL, 0, "%.*f", dp, val);
char *buffer = malloc(charsNeeded);
snprintf(buffer, charsNeeded, "%.*f", dp, val);
double result = atof(buffer);
free(buffer);
return result;
}
আমি এটি বলছি কারণ বর্তমানে শীর্ষ-ভোট দেওয়া উত্তরের সাথে এবং আরও বেশ কয়েকটি এখানে দেখানো পদ্ধতির - নিকটতম পূর্ণসংখ্যার সাথে বৃত্তাকার করে 100 দ্বারা গুণিত করা, এবং তারপরে আবার 100 দিয়ে ভাগ করা - দুটি উপায়ে ত্রুটিযুক্ত:
প্রথম ধরণের ত্রুটি চিত্রিত করতে - গোলাকার দিকটি কখনও কখনও ভুল হয়ে থাকে - এই প্রোগ্রামটি চালানোর চেষ্টা করুন:
int main(void) {
// This number is EXACTLY representable as a double
double x = 0.01499999999999999944488848768742172978818416595458984375;
printf("x: %.50f\n", x);
double res1 = dround(x, 2);
double res2 = round(100 * x) / 100;
printf("Rounded with snprintf: %.50f\n", res1);
printf("Rounded with round, then divided: %.50f\n", res2);
}
আপনি এই আউটপুটটি দেখতে পাবেন:
x: 0.01499999999999999944488848768742172978818416595459
Rounded with snprintf: 0.01000000000000000020816681711721685132943093776703
Rounded with round, then divided: 0.02000000000000000041633363423443370265886187553406
নোট করুন যে আমরা যে মানটি দিয়ে শুরু করেছি তা 0.015 এরও কম ছিল, এবং তাই 2 গুনে দশমিক স্থানে গোল করার সময় গাণিতিকভাবে সঠিক উত্তর 0.01 হয়। অবশ্যই, 0.01 ডাবল হিসাবে ঠিক উপস্থাপনযোগ্য নয় , তবে আমরা আমাদের ফলাফলটি 0.01 এর নিকটতম ডাবল হিসাবে প্রত্যাশা করি। ব্যবহার snprintf
আমাদের ফলাফল দেয়, কিন্তু ব্যবহার round(100 * x) / 100
আমাদের 0.02 দেয়, যা ভুল। কেন? কারণ 100 * x
ফলাফল হিসাবে আমাদের ঠিক 1.5 দেয়। 100 দ্বারা গুণ করলে এই দিকটি সঠিকভাবে পরিবর্তন হয়।
উদাহরণ হিসেবে বলা যায় দ্বিতীয় ত্রুটির ধরনের - ফলাফলের কখনও কখনও কারণে ভুল হচ্ছে * 100
এবং / 100
সত্যিই একে অপরের inverses হচ্ছে না - আমরা একটি খুব বড় সংখ্যা সঙ্গে একটি অনুরূপ ব্যায়াম করতে পারেন:
int main(void) {
double x = 8631192423766613.0;
printf("x: %.1f\n", x);
double res1 = dround(x, 2);
double res2 = round(100 * x) / 100;
printf("Rounded with snprintf: %.1f\n", res1);
printf("Rounded with round, then divided: %.1f\n", res2);
}
আমাদের সংখ্যায় এখন ভগ্নাংশও নেই; এটি একটি পূর্ণসংখ্যা মান, কেবল টাইপ সহ সঞ্চিত double
। সুতরাং গোল করার পরে ফলাফলটি একই সংখ্যাটি হওয়া উচিত যা আমরা শুরু করেছি, তাই না?
আপনি যদি উপরের প্রোগ্রামটি চালান, আপনি দেখতে পাবেন:
x: 8631192423766613.0
Rounded with snprintf: 8631192423766613.0
Rounded with round, then divided: 8631192423766612.0
উফ। আমাদের snprintf
পদ্ধতিটি আবার সঠিক ফলাফল দেয়, তবে বহুগুণ-তারপরে-পরে-পরে-ভাগ বিভাজন ব্যর্থ হয়। কারণ গাণিতিকভাবে সঠিক মান এটা 8631192423766613.0 * 100
, 863119242376661300.0
না একটি ডবল হিসাবে ঠিক representable হয়; নিকটতম মান হয় 863119242376661248.0
। আপনি যখন এটি পিছনে ১০০ দিয়ে ভাগ করবেন তখন আপনি পাবেন 8631192423766612.0
- আপনি যেটি দিয়ে শুরু করেছেন তার চেয়ে আলাদা সংখ্যা।
আশা করি এটি যথেষ্ট পরিমাণে প্রদর্শন যা roundf
বেশ কয়েকটি দশমিক স্থানে গোল করার জন্য ব্যবহারটি নষ্ট হয়ে গেছে এবং এর snprintf
পরিবর্তে আপনার ব্যবহার করা উচিত । যদি এটি আপনার কাছে ভয়ঙ্কর হ্যাকের মতো মনে হয় তবে সম্ভবত আপনি সিপাইথন যা করেন তা জ্ঞান দ্বারা আপনাকে আশ্বাস দেওয়া হবে ।
ব্যবহার float roundf(float x)
।
"বর্তমান বৃত্তাকার দিক নির্বিশেষে, শূন্য থেকে অর্ধেকটি কেস গোল করে, ভাসমান-বিন্দু বিন্যাসের নিকটতম পূর্ণসংখ্য মানের সাথে তাদের যুক্তির চারদিকে কাজ করে।" সি 11 ডিআর §7.12.9.5
#include <math.h>
float y = roundf(x * 100.0f) / 100.0f;
আপনার float
প্রয়োগের উপর নির্ভর করে যে সংখ্যাগুলি অর্ধপথ হিসাবে প্রদর্শিত হতে পারে তা নয়। যেহেতু ভাসমান-পয়েন্টটি সাধারণত বেস -২ ভিত্তিক হয়। তদুপরি, 0.01
সমস্ত " অর্ধপথ " কেসগুলির মধ্যে নিকটতম স্থানে অবিকল সংক্ষিপ্ত হওয়া সবচেয়ে চ্যালেঞ্জিং।
void r100(const char *s) {
float x, y;
sscanf(s, "%f", &x);
y = round(x*100.0)/100.0;
printf("%6s %.12e %.12e\n", s, x, y);
}
int main(void) {
r100("1.115");
r100("1.125");
r100("1.135");
return 0;
}
1.115 1.115000009537e+00 1.120000004768e+00
1.125 1.125000000000e+00 1.129999995232e+00
1.135 1.134999990463e+00 1.139999985695e+00
যদিও "1,115" "মধ্যপথে" 1.11 এবং 1.12 যখন রূপান্তরিত মধ্যে float
, মান 1.115000009537...
এবং আর "মধ্যপথে", কিন্তু নিকটস্থ করার 1.12 এবং চক্রের কাছাকাছি float
এর1.120000004768...
"1.125" হ'ল 1.12 এবং 1.13 এর মধ্যে "অর্ধপথ", যখন রূপান্তরিত হয় float
, মানটি হুবহু 1.125
এবং "অর্ধপথ" হয় । এটা তোলে নিকটতম এমনকি নিয়মের বন্ধন এবং চক্রের কারণে 1.13 দিকে চক্রের float
এর1.129999995232...
যদিও "1,135" "মধ্যপথে" 1.13 এবং 1.14 যখন রূপান্তরিত মধ্যে float
, মান 1.134999990463...
এবং আর "মধ্যপথে", কিন্তু নিকটস্থ করার 1.13 এবং চক্রের কাছাকাছি float
এর1.129999995232...
কোড ব্যবহার করা হয়
y = roundf(x*100.0f)/100.0f;
যদিও "1,135" "মধ্যপথে" 1.13 এবং 1.14 মধ্যে, যখন রূপান্তরিত হয় float
, মান 1.134999990463...
এবং আর "মধ্যপথে", কিন্তু কাছাকাছি থেকে 1.13 কিন্তু ভুল করার চক্রের float
এর 1.139999985695...
আরো সীমিত স্পষ্টতা কারণে float
বনাম double
। কোডিং লক্ষ্যের উপর নির্ভর করে এই ভুল মানটিকে সঠিক হিসাবে দেখা যেতে পারে।
আমি এই ম্যাক্রোটি ভাসমান সংখ্যার বৃত্তাকার জন্য তৈরি করেছি। এটি আপনার শিরোনামে / ফাইলের উপস্থিতিতে যুক্ত করুন
#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))
এখানে একটি উদাহরণ:
float x = ROUNDF(3.141592, 100)
এক্স সমান 3.14 :)
double f_round(double dval, int n)
{
char l_fmtp[32], l_buf[64];
char *p_str;
sprintf (l_fmtp, "%%.%df", n);
if (dval>=0)
sprintf (l_buf, l_fmtp, dval);
else
sprintf (l_buf, l_fmtp, dval);
return ((double)strtod(l_buf, &p_str));
}
n
দশমিক সংখ্যা এখানে
উদাহরণ:
double d = 100.23456;
printf("%f", f_round(d, 4));// result: 100.2346
printf("%f", f_round(d, 2));// result: 100.23
dval
3) অদ্ভুত if
/ else
ব্লক যেখানে আপনি প্রতিটি শাখায় ঠিক একই জিনিস করেন , এবং 4) sprintf
দ্বিতীয় sprintf
কলের জন্য ফর্ম্যাট স্পেসিফায়ার তৈরি করতে অত্যধিক জটিল ব্যবহার ; কেবলমাত্র .*
একই sprintf
কলটিতে যুক্তি হিসাবে দ্বৈত মান এবং দশমিক স্থানের সংখ্যা ব্যবহার এবং পাস করা সহজ ।
#define roundz(x,d) ((floor(((x)*pow(10,d))+.5))/pow(10,d))
a = 8.000000
sqrt(a) = r = 2.828427
roundz(r,2) = 2.830000
roundz(r,3) = 2.828000
roundz(r,5) = 2.828430
আমাকে প্রথমে এই প্রশ্নের আরও একটি উত্তর যুক্ত করার জন্য আমার যুক্তিকে ন্যায়সঙ্গত করার চেষ্টা করতে দিন। একটি আদর্শ বিশ্বে, গোল করা আসলে কোনও বড় বিষয় নয়। তবে, বাস্তব সিস্টেমে আপনার বেশ কয়েকটি সমস্যার সাথে লড়াই করতে হতে পারে যার ফলস্বরূপ গোলটি হতে পারে যা আপনি প্রত্যাশা নাও করতে পারেন। উদাহরণস্বরূপ, আপনি আর্থিক হিসাব সম্পাদন করতে পারেন যেখানে চূড়ান্ত ফলাফলগুলি গোল করা হয় এবং 2 দশমিক স্থান হিসাবে ব্যবহারকারীদের কাছে প্রদর্শিত হয়; এই একই মানগুলি একটি ডেটাবেজে স্থির নির্ভুলতার সাথে সঞ্চিত থাকে যা 2 টিরও বেশি দশমিক স্থান অন্তর্ভুক্ত করতে পারে (বিভিন্ন কারণে; রাখার জন্য কোনও অনুকূল সংখ্যা নেই ... প্রতিটি সিস্টেমকে অবশ্যই সমর্থন করা উচিত নির্দিষ্ট পরিস্থিতিতে নির্ভর করে, যেমন ছোট আইটেম যার দাম ইউনিট প্রতি এক পয়সা ভগ্নাংশ); এবং, ভাসমান পয়েন্ট গণনাগুলি মানগুলিতে সম্পাদিত হয় যেখানে ফলাফলগুলি আরও / বিয়োগ ইপিসিলন হয় are আমি কয়েক বছর ধরে এই বিষয়গুলির মুখোমুখি হয়েছি এবং নিজের কৌশলটি বিকশিত করছি। আমি দাবি করব না যে আমি প্রতিটি দৃশ্যের মুখোমুখি হয়েছি বা সর্বোত্তম উত্তর পেয়েছি, তবে নীচে এখনও পর্যন্ত আমার পদ্ধতির একটি উদাহরণ যা এই সমস্যাগুলিকে কাটিয়ে উঠেছে:
ধরুন, 6 টি দশমিক স্থানগুলি নিম্নলিখিত বৃত্তাকার ফাংশন / পদ্ধতিটি ব্যবহার করে ফ্লোট / ডাবল (নির্দিষ্ট প্রয়োগের জন্য একটি স্বেচ্ছাসেবী সিদ্ধান্ত) গণনার জন্য যথাযথ নির্ভুলতা হিসাবে বিবেচিত:
double Round(double x, int p)
{
if (x != 0.0) {
return ((floor((fabs(x)*pow(double(10.0),p))+0.5))/pow(double(10.0),p))*(x/fabs(x));
} else {
return 0.0;
}
}
ফলাফল উপস্থাপনের জন্য 2 দশমিক স্থানে গোল করে এই হিসাবে সম্পাদন করা যেতে পারে:
double val;
// ...perform calculations on val
String(Round(Round(Round(val,8),6),2));
জন্য val = 6.825
, ফলাফল 6.83
হিসাবে প্রত্যাশিত হয়।
জন্য val = 6.824999
, ফলাফল 6.82
। এখানে অনুমান করা হয় যে গণনাটি ঠিক ফলাফল করেছিল 6.824999
এবং 7 তম দশমিক স্থান শূন্য।
জন্য val = 6.8249999
, ফলাফল 6.83
। 9
এই ক্ষেত্রে 7 ম দশমিক স্থান থাকার কারণে কার্যটি Round(val,6)
প্রত্যাশিত ফলাফল দেয় give এই ক্ষেত্রে, পিছনে যে কোনও সংখ্যক হতে পারে 9
।
জন্য val = 6.824999499999
, ফলাফল 6.83
। প্রথম পদক্ষেপ হিসাবে অষ্টম দশমিক স্থানে গোল করে, অর্থাত্ Round(val,8)
একটি ন্যক্কারজনক কেসটির যত্ন নেয় যার মাধ্যমে গণনা করা ভাসমান পয়েন্টের ফলাফলটি গণনা করা হয় 6.8249995
, তবে অভ্যন্তরীণভাবে এটি প্রতিনিধিত্ব করা হয় 6.824999499999...
।
অবশেষে, প্রশ্ন থেকে উদাহরণ ... val = 37.777779
ফলাফল আসে 37.78
।
এই পদ্ধতির আরও সাধারণীকরণ করা যেতে পারে:
double val;
// ...perform calculations on val
String(Round(Round(Round(val,N+2),N),2));
যেখানে এন হ'ল ফ্লোট / ডাবলসের সমস্ত মধ্যবর্তী গণনার জন্য যথাযথ রক্ষণাবেক্ষণ করা হয়। এটি নেতিবাচক মানগুলিতেও কাজ করে। আমি জানি না এই পদ্ধতিটি সমস্ত সম্ভাবনার জন্য গাণিতিকভাবে সঠিক কিনা।
কোনও সংখ্যার বৃত্তাকার জন্য সাধারণ সি কোড:
float n = 3.56;
printf("%.f", n);
এটি আউটপুট দেবে:
4
... অথবা আপনি এটি কোনও লাইব্রেরি ছাড়াই পুরানো কায়দায় করতে পারেন:
float a = 37.777779;
int b = a; // b = 37
float c = a - b; // c = 0.777779
c *= 100; // c = 77.777863
int d = c; // d = 77;
a = b + d / (float)100; // a = 37.770000;
অবশ্যই যদি আপনি নম্বরটি থেকে অতিরিক্ত তথ্য সরাতে চান।
এই ফাংশনটি সংখ্যা এবং নির্ভুলতা নেয় এবং গোলাকার নম্বরটি প্রদান করে
float roundoff(float num,int precision)
{
int temp=(int )(num*pow(10,precision));
int num1=num*pow(10,precision+1);
temp*=10;
temp+=5;
if(num1>=temp)
num1+=10;
num1/=10;
num1*=10;
num=num1/pow(10,precision+1);
return num;
}
এটি ভাসমান পয়েন্ট সংখ্যাটি বিন্দুতে বাম স্থানান্তরিত করে এবং পাঁচটিরও বেশি শর্তের জন্য পরীক্ষা করে রূপান্তর করে।
float
(এবংdouble
) দশমিক ভাসমান-বিন্দু নয় - এগুলি বাইনারি ভাসমান-বিন্দু - সুতরাং দশমিক অবস্থানগুলিতে গোল করা অর্থহীন। তবে আপনি আউটপুটটি বৃত্তাকার করতে পারেন।