সি-এর দশমিক পয়েন্টের পরে আমি কীভাবে কেবল দুটি স্থানে একটি ফ্লোট মানকে সীমাবদ্ধ করব?


215

আমি কীভাবে একটি ভাসমানের মানকে (যেমন 37.777779) দুটি দশমিক স্থানে (37.78) সি এর মধ্যে গোল করতে পারি?


15
আপনি নিজেই সংখ্যার সঠিকভাবে গোল করতে পারবেন না, কারণ float(এবং double) দশমিক ভাসমান-বিন্দু নয় - এগুলি বাইনারি ভাসমান-বিন্দু - সুতরাং দশমিক অবস্থানগুলিতে গোল করা অর্থহীন। তবে আপনি আউটপুটটি বৃত্তাকার করতে পারেন।
পাভেল মিনায়েভ

63
এটি অর্থহীন নয়; এটা অক্ষম। বেশ পার্থক্য আছে।
ব্রুকস মূসা

2
আপনি কোন ধরণের গোলের প্রত্যাশা করছেন? হাফ-আপ বা নিকটতম এমনকি রাউন্ডিং?
ট্রুথসাইকার রাঙ্গওয়ান

উত্তর:


407

যদি আপনি কেবল আউটপুট উদ্দেশ্যে সংখ্যার বৃত্তাকার করতে চান তবে "%.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 */

লক্ষ্য করুন যে আপনি বেছে নিতে পারেন যে তিনটি পৃথক রাউন্ডিং বিধি রয়েছে: বৃত্তাকার ডাউন (অর্থাত্, দুটি দশমিক স্থান পরে কাটা), কাছাকাছি থেকে গোলাকার, এবং রাউন্ড আপ। সাধারণত, আপনি কাছাকাছি থেকে কাছাকাছি চান।

অন্য কয়েকজন যেমন উল্লেখ করেছেন যে, ভাসমান পয়েন্ট উপস্থাপনের ছড়াছড়িগুলির কারণে, এই বৃত্তাকার মানগুলি সম্ভবত "সুস্পষ্ট" দশমিক মান নাও হতে পারে তবে তারা খুব নিকটেই থাকবে।

রাউন্ডিং সম্পর্কে অনেক বেশি (অনেক!) আরও তথ্যের জন্য, এবং বিশেষত নিকটতমকে গোল করার জন্য টাই-ব্রেকিং বিধি সম্পর্কে, রাউন্ডিং সম্পর্কিত উইকিপিডিয়া নিবন্ধটি দেখুন ।


4
এটি নির্বিচারে নির্ভুলতার জন্য বৃত্তাকার সমর্থন করতে সংশোধন করা যেতে পারে?

1
@ স্লেটার আপনি যখন 'নির্বিচারে নির্ভুলতা' বলছেন, আপনি কি দুটি দশমিক জায়গার পরিবর্তে তিনটি গোল করার বিষয়ে জিজ্ঞাসা করছেন, বা সীমাহীন নির্ভুলতা দশমিক মান প্রয়োগকারী লাইব্রেরি ব্যবহার করছেন? যদি প্রাক্তন হয়, তবে আমি যা আশা করি তা স্থির 100 এর সুস্পষ্ট সামঞ্জস্য হয় make অন্যথায়, আপনি যে মাল্টি নির্ভুল গ্রন্থাগারটি ব্যবহার করছেন ঠিক তার সাথে উপরে দেখানো ঠিক একই গণনা করুন।
ডেল হ্যাগলুন্ড

2
প্রাক্তন, আপনাকে ধন্যবাদ 100 এর প্রতিস্থাপনের সাথে সামঞ্জস্যতা (10, (পূর্বনির্ধারিত পছন্দসই)?

3
হাঁ। দশমিক দশমিক কোটির পরে গোল করতে, 10 ^ কে এর স্কেল ফ্যাক্টর ব্যবহার করুন। যদি আপনি হাতে দশমিক মানগুলি হাতের মুঠোয় লিখে 10 এর গুণক দিয়ে খেলেন তবে এটি দেখতে খুব সহজ হওয়া উচিত Supp ধরুন আপনি 1.23456789 মানের সাথে কাজ করছেন এবং এটি 3 দশমিক স্থানে নিয়ে যেতে চান। আপনার কাছে উপলব্ধ অপারেশনটি পূর্ণসংখ্যার সাথে গোল । সুতরাং, আপনি কীভাবে প্রথম তিনটি দশমিক স্থান সরিয়ে নিয়েছেন যাতে তারা দশমিক বিন্দু থেকে যায়? আমি আশা করি এটি পরিষ্কার হয়ে গেছে যে আপনি 10 ^ 3 দ্বারা গুন করবেন। এখন আপনি একটি পূর্ণসংখ্যার মানটি গোল করতে পারেন। এরপরে, আপনি তিনটি নিম্ন অর্ডার সংখ্যা 10 ^ 3 দ্বারা ভাগ করে পিছনে রেখেছেন।
ডেল হ্যাগলুন্ড

1
আমি কি doublesকোনওভাবে এই কাজটি করতে পারি ? কাজ করার আমি চাই :( (ব্যবহার বলে মনে হচ্ছে না floorএবং ceil)।
শ্রীমতি কেউই

87

প্রিন্টেফ% এফ ব্যবহার করে । এটি কেবলমাত্র 2 দশমিক পয়েন্ট মুদ্রণ করে।

উদাহরণ:

printf("%.2f", 37.777779);

আউটপুট:

37.77

নির্ভুলতার কোনও ক্ষতি না হওয়ায় এই উপায়টি আরও ভাল।
অ্যালবার্ট

2
@ অ্যালবার্ট এটিকেও প্রবাহিত হওয়ার মতো কোনও floatপরিসীমা হ্রাস করার সুবিধা রয়েছে val * 100
chux -

42

ধরে নিই যে আপনি মুদ্রণের মানটির চারপাশে কথা বলছেন, তারপরে অ্যান্ড্রু কোলসন এবং আরকের উত্তর সঠিক:

printf("%.2f", 37.777779);

তবে মনে রাখবেন যে আপনি যদি অভ্যন্তরীণ ব্যবহারের জন্য সংখ্যাটি ঠিক ৩ 37. to78 তে গোল করার লক্ষ্য রাখছেন (উদাহরণস্বরূপ অন্য মানের সাথে তুলনা করা) তবে ভাসমান পয়েন্ট সংখ্যাগুলি কাজ করার কারণে এটি ভাল ধারণা নয়: আপনি সাধারণত না ভাসমান পয়েন্টের জন্য সমতা তুলনা করতে চাই, পরিবর্তে একটি লক্ষ্য মান +/- একটি সিগমা মান ব্যবহার করুন। বা একটি পরিচিত নির্ভুলতার সাথে স্ট্রিং হিসাবে নম্বরটি এনকোড করুন এবং এটি তুলনা করুন।

সম্পর্কিত প্রশ্নটির গ্রেগ হিউগিলের উত্তরের লিঙ্কটি দেখুন , যা আপনাকে আর্থিক গণনার জন্য ভাসমান পয়েন্ট কেন ব্যবহার করবেন না তাও অন্তর্ভুক্ত করে।


1
প্রশ্নের পিছনে প্রশ্নটি কী হতে পারে (বা যে প্রশ্নটির পিছনে প্রশ্নটি হওয়া উচিত ছিল!) সম্বোধনের জন্য উপস্থাপিত! এটি একটি বরং গুরুত্বপূর্ণ পয়েন্ট।
ব্রুকস মূসা

প্রকৃতপক্ষে 37.78 ভাসমান পয়েন্ট দ্বারা উপস্থাপন করা যেতে পারে। যথাযথতার জন্য ফ্লোটের 11 থেকে 12 সংখ্যা রয়েছে। এটি 3778 377.8 বা সমস্ত ধরণের 4 দশমিক সংখ্যার ঠিকানার জন্য যথেষ্ট enough
বেনামে হোয়াইট

@ হারিয়ন্তো সিউ হ্যাঁ মোটামুটি, আমি আমার উত্তরটি কিছুটা সম্পাদনা করেছি।
জন কার্টার

গতিশীল নির্ভুলতা:printf("%.*f", (int)precision, (double)number);
মিনহাস কামাল

24

এটি সম্পর্কে:

float value = 37.777779;
float rounded = ((int)(value * 100 + .5) / 100.0);

4
-1: ক) এটি নেতিবাচক সংখ্যার জন্য কাজ করবে না (ঠিক আছে, উদাহরণটি ইতিবাচক তবে এখনও)। খ) আপনি উল্লেখ করবেন না যে সঠিক দশমিক মানটি ফ্লোটে সংরক্ষণ করা অসম্ভব
জন কার্টার

32
@ এখানে থেকে: (ক) আপনি ঠিক বলেছেন (খ) এটি কী? একটি হাই স্কুল পরীক্ষা?
ড্যানিল

1
কেন আপনি 0.5 যোগ করেছেন?
মুহাম্মাদ তাইয়েব

1
রাউন্ডিং বিধি অনুসরণ করা প্রয়োজন।
ড্যানিল

1
@ ডানিল মন্তব্যের প্রসঙ্গে রাউন্ডিং বিধিগুলি নিকটতমের নিকটবর্তী
শমিল দ্য ক্যাট

20
printf("%.2f", 37.777779);

আপনি যদি সি-স্ট্রিংয়ে লিখতে চান:

char number[24]; // dummy size, you should take care of the size!
sprintf(number, "%.2f", 37.777779);

@ সিনান: সম্পাদনা কেন? @ আরাক: না, আপনার আকারের যত্ন নেওয়া উচিত :)। স্নিপ্রিন্টফ () ব্যবহার করুন।
aib

1
@ আইয়েব: আমি অনুমান করব কারণ / ** / সি সি স্টাইলের মন্তব্য এবং প্রশ্নটি সি
মাইকেল হরেন

5
C89 কেবল অনুমোদিত / ** / - শৈলীতে, C99 // - শৈলীর জন্য সমর্থন প্রবর্তন করেছে। একটি খোঁড়া / পুরানো সংকলক (বা জোর করে C89 মোড) ব্যবহার করুন এবং আপনি // - শৈলী ব্যবহার করতে অক্ষম হবেন। এটি বলার পরে, এটি ২০০৯, আসুন সেগুলি উভয় সি এবং সি ++ স্টাইল বিবেচনা করুন।
অ্যান্ড্রু কোলসন

11

floatঅন্যকে গোল করার কোনও উপায় নেই floatকারণ গোলাকারটি floatউপস্থাপনযোগ্য নাও হতে পারে (ভাসমান-পয়েন্ট সংখ্যাগুলির সীমাবদ্ধতা)। উদাহরণস্বরূপ, আপনি 37.777779 থেকে 37.78 গোল করে বলুন তবে নিকটতম প্রতিনিধিত্বযোগ্য সংখ্যা 37.781।

তবে, আপনি একটি ফর্ম্যাট স্ট্রিং ফাংশন ব্যবহার করে "বৃত্তাকার" করতে পারেনfloat


3
এটি বলা "এর চেয়ে আলাদা নয় যে" দুটি ফ্লোট বিভক্ত করার এবং কোনও ফ্লোট পাওয়ার কোনও উপায় নেই, কারণ বিভক্ত ফলাফলটি উপস্থাপনযোগ্য হতে পারে না, "যা সঠিকভাবে সত্য হতে পারে তবে এটি অপ্রাসঙ্গিক। সংযোজন হিসাবে মৌলিক কোনও কিছুর জন্য এমনকি ভাসমানগুলি সর্বদা অযোগ্য; অনুমানটি সর্বদা এটি যে আপনি আসলে যা পান তা হ'ল "ভাসমানটি যা সর্বাধিক ঘনিষ্ঠভাবে সঠিক গোলাকার উত্তরটির সাথে সন্নিবিষ্ট হয়"।
ব্রুকস মুসা 3 ই

আমার অর্থ হ'ল আপনি এক floatথেকে দশমিক দশমিক জায়গায় গোল করতে পারবেন না এবং তারপরে ফলাফলটি সর্বদা n দশমিক স্থানের আশা করতে পারেন। আপনি এখনও একটি পাবেন float, আপনি যেটি প্রত্যাশা করেছিলেন তা নয় not
অ্যান্ড্রু কিটন 3

9

এছাড়াও, আপনি যদি সি ++ ব্যবহার করেন তবে আপনি ঠিক এর মতো একটি ফাংশন তৈরি করতে পারেন:

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);

7

আপনি এখনও ব্যবহার করতে পারেন:

float ceilf(float x); // don't forget #include <math.h> and link with -lm.

উদাহরণ:

float valueToRound = 37.777779;
float roundedValue = ceilf(valueToRound * 100) / 100;

এটি দশমিক পয়েন্টে কেটে যায় (অর্থাত্ 37 টি উত্পাদন করবে) এবং তাকে দশমিক পয়েন্টের পরে দুটি জায়গায় যেতে হবে ।
পাভেল মিনায়েভ

দশমিক পয়েন্টের পরে দুটি স্থানে গোল করা একটি তুচ্ছ পরিবর্তন, যদিও (তবে এখনও উত্তরে উল্লেখ করা উচিত; জিরোকুল, একটি সম্পাদনা যুক্ত করতে চান?): ভাসা গোলাকারভ্যালু = সিলফ (মানফলক * 100.0) / 100.0;
ব্রুকস মূসা

ঘুমের রাজ্যে :)
জিরোকুল

কীভাবে এই সমাধানটি আরও জনপ্রিয় নয়? এটি ন্যূনতম কোড সহ ঠিক কীভাবে কাজ করবে তা কাজ করে। এর সাথে কিছু সতর্কতা আছে?
অ্যান্ডি

7

সি ++ এ (বা সি-স্টাইলের ক্যাসেট সহ সিতে), আপনি ফাংশনটি তৈরি করতে পারেন:

/* 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 টি ভেরিয়েবল তৈরি করার দরকার নেই, তবে আমি সেগুলি সেখানে রেখেছি যাতে আপনি যুক্তি দেখতে পারেন। সম্ভবত আরও সহজ সমাধান রয়েছে, তবে এটি আমার পক্ষে ভাল কাজ করে - বিশেষত যেহেতু এটি আমার প্রয়োজন হিসাবে দশমিক জায়গার পরে অঙ্কের সংখ্যা সামঞ্জস্য করতে দেয়।


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 দিয়ে ভাগ করা - দুটি উপায়ে ত্রুটিযুক্ত:

  • কিছু মানগুলির জন্য এটি ভুল দিকে গোল হয়ে যাবে কারণ ভাসমান পয়েন্ট সংখ্যাগুলির অপ্রচলনের কারণে 100 দ্বারা গুণিতকটি 4 থেকে 5 বা তার বিপরীতে গোলাকার দিক নির্ধারণ করে দশমিক অঙ্ক পরিবর্তন করে because
  • কিছু মানগুলির জন্য, গুণমান এবং তারপরে ১০০ দিয়ে বিভাজকটি রাউন্ড-ট্রিপ করে না, অর্থাত কোনও রাউন্ডিং না করা হলেও শেষ ফলাফলটি ভুল হবে that

প্রথম ধরণের ত্রুটি চিত্রিত করতে - গোলাকার দিকটি কখনও কখনও ভুল হয়ে থাকে - এই প্রোগ্রামটি চালানোর চেষ্টা করুন:

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পরিবর্তে আপনার ব্যবহার করা উচিত । যদি এটি আপনার কাছে ভয়ঙ্কর হ্যাকের মতো মনে হয় তবে সম্ভবত আপনি সিপাইথন যা করেন তা জ্ঞান দ্বারা আপনাকে আশ্বাস দেওয়া হবে ।


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

আহেম ... শেষের নিকটে সালাদ শব্দের জন্য দুঃখিত, এটি সম্পাদনায় এখন অনেক দেরি হয়ে গেছে। আমি যা বলতে চাইছিলাম তা হ'ল "... প্রিন্টফ এবং বন্ধুদের নিরাপদ রাখতে তাদের প্রচুর প্রচেষ্টা করা হয়েছিল ..."
ডেল হাগলুন্ড

4

ব্যবহার 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। কোডিং লক্ষ্যের উপর নির্ভর করে এই ভুল মানটিকে সঠিক হিসাবে দেখা যেতে পারে।


4

আমি এই ম্যাক্রোটি ভাসমান সংখ্যার বৃত্তাকার জন্য তৈরি করেছি। এটি আপনার শিরোনামে / ফাইলের উপস্থিতিতে যুক্ত করুন

#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))

এখানে একটি উদাহরণ:

float x = ROUNDF(3.141592, 100)

এক্স সমান 3.14 :)


এটি কেটে যায় তবে প্রশ্নটি অনুরোধ করে round অতিরিক্তভাবে, এটি ভাসমান-পয়েন্ট অপারেশনগুলিতে গোল করার ত্রুটি সাপেক্ষে।
এরিক পোস্টপিসিল

3
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

-১ চারটি কারণে: ১) ব্যাখ্যার অভাব, ২) ওভারফ্লো বাফারের ঝুঁকি - এটি উপচে পড়বে, এবং তাই সম্ভবত সম্ভবত ক্র্যাশ হবে dval3) অদ্ভুত if/ elseব্লক যেখানে আপনি প্রতিটি শাখায় ঠিক একই জিনিস করেন , এবং 4) sprintfদ্বিতীয় sprintfকলের জন্য ফর্ম্যাট স্পেসিফায়ার তৈরি করতে অত্যধিক জটিল ব্যবহার ; কেবলমাত্র .*একই sprintfকলটিতে যুক্তি হিসাবে দ্বৈত মান এবং দশমিক স্থানের সংখ্যা ব্যবহার এবং পাস করা সহজ ।
মার্ক

3

কোড সংজ্ঞা:

#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

0

আমাকে প্রথমে এই প্রশ্নের আরও একটি উত্তর যুক্ত করার জন্য আমার যুক্তিকে ন্যায়সঙ্গত করার চেষ্টা করতে দিন। একটি আদর্শ বিশ্বে, গোল করা আসলে কোনও বড় বিষয় নয়। তবে, বাস্তব সিস্টেমে আপনার বেশ কয়েকটি সমস্যার সাথে লড়াই করতে হতে পারে যার ফলস্বরূপ গোলটি হতে পারে যা আপনি প্রত্যাশা নাও করতে পারেন। উদাহরণস্বরূপ, আপনি আর্থিক হিসাব সম্পাদন করতে পারেন যেখানে চূড়ান্ত ফলাফলগুলি গোল করা হয় এবং 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.839এই ক্ষেত্রে 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));

যেখানে এন হ'ল ফ্লোট / ডাবলসের সমস্ত মধ্যবর্তী গণনার জন্য যথাযথ রক্ষণাবেক্ষণ করা হয়। এটি নেতিবাচক মানগুলিতেও কাজ করে। আমি জানি না এই পদ্ধতিটি সমস্ত সম্ভাবনার জন্য গাণিতিকভাবে সঠিক কিনা।



-1

... অথবা আপনি এটি কোনও লাইব্রেরি ছাড়াই পুরানো কায়দায় করতে পারেন:

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;

অবশ্যই যদি আপনি নম্বরটি থেকে অতিরিক্ত তথ্য সরাতে চান।


-2

এই ফাংশনটি সংখ্যা এবং নির্ভুলতা নেয় এবং গোলাকার নম্বরটি প্রদান করে

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;
}

এটি ভাসমান পয়েন্ট সংখ্যাটি বিন্দুতে বাম স্থানান্তরিত করে এবং পাঁচটিরও বেশি শর্তের জন্য পরীক্ষা করে রূপান্তর করে।

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