सी में दशमलव बिंदु के बाद मैं केवल दो स्थानों पर एक फ्लोट मूल्य को कैसे प्रतिबंधित करूं?


215

मैं C में दो दशमलव स्थानों (37.78) पर फ्लोट वैल्यू (जैसे 37.777779) कैसे राउंड कर सकता हूं?


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
@slater जब आप 'मनमानी परिशुद्धता' कहते हैं, तो क्या आप दो दशमलव स्थानों के बजाय तीन, या उन पुस्तकालयों का उपयोग करने के बारे में पूछ रहे हैं, या उन पुस्तकालयों का उपयोग कर रहे हैं जो अनबाउंड सटीक दशमलव मानों को लागू करते हैं? यदि पूर्व, मैं जो आशा करता हूं कि निरंतर 100 के लिए स्पष्ट समायोजन है; अन्यथा, ऊपर दिखाए गए सटीक गणनाओं को करें, बस जो भी बहु-सटीक पुस्तकालय आपके द्वारा उपयोग किए जा रहे हैं।
डेल हाग्लगंड

2
@DaleHagglung पूर्व, धन्यवाद। क्या 100 को पॉव (10, (इंट) वांछितप्रेसेप) के साथ बदलने का समायोजन है?

3
हां। K दशमलव स्थानों के बाद गोल करने के लिए, 10 ^ k के स्केल कारक का उपयोग करें। यह देखना वास्तव में आसान होना चाहिए कि क्या आप कुछ दशमलव मानों को हाथ से लिखते हैं और 10. के गुणकों के साथ खेलते हैं। मान लीजिए कि आप 1.23456789 मान के साथ काम कर रहे हैं, और इसे 3 दशमलव स्थानों पर गोल करना चाहते हैं। आपके लिए उपलब्ध ऑपरेशन पूर्णांक के लिए गोल है । तो, आप पहले तीन दशमलव स्थानों को कैसे स्थानांतरित करेंगे ताकि वे दशमलव बिंदु से बचे रहें? मुझे आशा है कि यह स्पष्ट है कि आप 10 ^ 3 से गुणा करेंगे। अब आप उस मान को पूर्णांक तक गोल कर सकते हैं। इसके बाद, आप तीन निम्न क्रम अंकों को 10 ^ 3 से विभाजित करके वापस डालते हैं।
डेल हाग्लगंड

1
क्या मैं यह काम doublesकिसी तरह कर सकता हूं ? लगता है कि मैं जो काम करना चाहता हूँ वह नहीं करता :( (का उपयोग करके floorऔर ceil)
सुश्री कोई भी

87

प्रिंट में % .2f का उपयोग करना । यह केवल 2 दशमलव अंक प्रिंट करता है।

उदाहरण:

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

आउटपुट:

37.77

यह तरीका बेहतर है क्योंकि इसमें परिशुद्धता का कोई नुकसान नहीं है।
अल्बर्ट

2
@ अल्बर्ट के पास अतिप्रवाह के कारण floatरेंज के कोई नुकसान का लाभ नहीं है val * 100
chux -

42

मान लें कि आप मुद्रण के लिए मूल्य दौर के बारे में बात कर रहे हैं, तो एंड्रयू Coleson और अरक के जवाब सही हैं:

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

लेकिन ध्यान दें कि यदि आप आंतरिक उपयोग के लिए संख्या को 37.78 पर गोल करने का लक्ष्य बना रहे हैं (उदाहरण के लिए किसी अन्य मूल्य के खिलाफ तुलना करने के लिए), तो यह एक अच्छा विचार नहीं है, जिस तरह से फ्लोटिंग पॉइंट नंबर काम करते हैं: आप आमतौर पर नहीं करते हैं फ्लोटिंग पॉइंट के लिए समानता तुलना करना चाहते हैं, इसके बजाय एक लक्ष्य मान +/- एक सिग्मा मान का उपयोग करें। या संख्या को एक ज्ञात परिशुद्धता के साथ एक स्ट्रिंग के रूप में एन्कोड करें, और तुलना करें।

संबंधित प्रश्न के लिए ग्रेग हेगिल के उत्तर के लिंक को देखें , जिसमें यह भी शामिल है कि आपको वित्तीय गणना के लिए फ़्लोटिंग पॉइंट का उपयोग क्यों नहीं करना चाहिए।


1
प्रश्न के पीछे प्रश्न क्या हो सकता है (या प्रश्न के पीछे जो प्रश्न होना चाहिए था!) ​​को संबोधित करने के लिए तैयार किया गया। यह एक महत्वपूर्ण बिंदु है।
ब्रूक्स मूसा

वास्तव में 37.78 को फ्लोटिंग पॉइंट द्वारा प्रस्तुत किया जा सकता है। फ्लोट में प्रिडिक्शन के लिए 11 से 12 अंक होते हैं। यह 3778 377.8 या सभी प्रकार के 4 दशमलव अंकों को संबोधित करने के लिए पर्याप्त होना चाहिए।
बेनामी व्हाइट

@HaryantoCiu हाँ काफी निष्पक्ष, मैंने अपना जवाब थोड़ा सा दिया है।
जॉन कार्टर

गतिशील सटीकता:printf("%.*f", (int)precision, (double)number);
मिन्हास कमल

24

इस बारे में कैसा है:

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

4
-1: ए) यह नकारात्मक संख्याओं के लिए काम नहीं करेगा (ठीक है, उदाहरण सकारात्मक है लेकिन फिर भी)। बी) आप उल्लेख नहीं करते हैं कि फ्लोट में सटीक दशमलव मान को स्टोर करना असंभव है
जॉन कार्टर

32
@therefromhere: (ए) आप सही हैं (बी) यह क्या है? एक हाई स्कूल की परीक्षा?
डेनियल

1
आपने 0.5 क्यों जोड़ा?
मुहम्मद तेय्यब

1
राउंडिंग नियमों का पालन करना आवश्यक है।
डेनियल

1
@Daniil टिप्पणी के संदर्भ में गोलाई के नियम निकटतम हैं
शमिल द कैट

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

यदि आप सी-स्ट्रिंग लिखना चाहते हैं:

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

@ सीन: क्यों संपादित करें? @ आरा: नहीं, आपको आकार का ध्यान रखना चाहिए :)। स्नप्रिंट () का उपयोग करें।
एआईबी

1
@ ऐब: मुझे लगता है क्योंकि / ** / सी शैली की टिप्पणियाँ हैं और सवाल C के लिए टैग किया गया है
माइकल हरेन

5
C89 ने केवल / ** / शैली की अनुमति दी, C99 ने // - शैली के लिए समर्थन पेश किया। एक लंगड़ा / पुराने संकलक का उपयोग करें (या C89 मोड को बल दें) और आप // - शैली का उपयोग करने में असमर्थ होंगे। यह कहते हुए कि, यह 2009 है, आइए उन दोनों पर विचार करें C और C ++ शैली।
एंड्रयू कोलेसन

11

वहाँ दौर एक के लिए एक रास्ता नहीं है floatदूसरे के लिए floatक्योंकि गोल floatप्रदर्शनीय नहीं हो सकता है (फ्लोटिंग प्वाइंट नंबर की एक सीमा)। उदाहरण के लिए, आप 37.777779 से 37.78 के बीच में हैं, लेकिन सबसे अधिक प्रतिनिधित्व करने वाली संख्या 37.781 है।

हालाँकि, आप एक प्रारूप स्ट्रिंग फ़ंक्शन का उपयोग करके "राउंड" कर सकते हैंfloat


3
यह कहने से अलग नहीं है कि "दो फ़्लोट्स को विभाजित करने और एक फ़्लोट प्राप्त करने का कोई तरीका नहीं है, क्योंकि विभाजित परिणाम प्रतिनिधित्व योग्य नहीं हो सकता है," जो वास्तव में सही हो सकता है लेकिन अप्रासंगिक है। फ़्लोट्स हमेशा बेवजह होते हैं, यहां तक ​​कि कुछ के लिए भी मूल के रूप में इसके अलावा; धारणा हमेशा यह है कि आपको वास्तव में क्या मिलता है "फ्लोट जो कि सबसे करीब से सटीक गोल उत्तर का अनुमान लगाता है"।
ब्रूक्स मूसा

मेरा आशय यह है कि आप floatn से n दशमलव स्थानों पर चक्कर नहीं लगा सकते हैं और फिर परिणाम की अपेक्षा हमेशा n दशमलव स्थानों की होगी। आप अभी भी एक मिलेगा float, बस एक आप की उम्मीद नहीं है।
एंड्रयू केटॉन

9

इसके अलावा, यदि आप C ++ का उपयोग कर रहे हैं, तो आप इस तरह से एक फंक्शन बना सकते हैं:

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 का उत्पादन करेगा), और उसे दशमलव बिंदु के बाद दो स्थानों पर चक्कर लगाना होगा।
पावेल मिनाएव

दशमलव बिंदु के बाद दो स्थानों पर गोलाई एक तुच्छ भिन्नता है, हालाँकि (लेकिन फिर भी इसका उत्तर में उल्लेख किया जाना चाहिए; ज़ीरकोल, एक संपादन जोड़ना चाहते हैं?): फ्लोट राउंडवैल्यू = सीलिफ़ (valueToRatoe / 100.0) / 100.0;
ब्रूक्स मूसा

नींद की अवस्था में :)
ZeroCool

यह समाधान कैसे आया और अधिक लोकप्रिय नहीं है? यह ठीक उसी तरह काम करता है जैसे इसे न्यूनतम कोड के साथ होना चाहिए। क्या इसके साथ कुछ चेतावनी है?
एंडी

7

C ++ में (या C- शैली के कलाकारों के साथ C) में, आप फ़ंक्शन बना सकते हैं:

/* 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 या इसके विपरीत गोल दिशा निर्धारित करने वाला परिवर्तन होता है, जो फ्लोटिंग पॉइंट नंबरों की गड़बड़ी के कारण होता है।
  • कुछ मानों के लिए, गुणा करना और फिर 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सही मायने में एक-दूसरे के विपरीत नहीं होने के कारण - हम एक बहुत बड़ी संख्या के साथ एक समान व्यायाम कर सकते हैं:

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एक डबल के रूप में बिल्कुल प्रतिनिधित्व योग्य नहीं है; निकटतम मूल्य है 863119242376661248.0। जब आप उस पीठ को 100 से विभाजित करते हैं, तो आप प्राप्त करते हैं 8631192423766612.0- आपके द्वारा शुरू की गई एक अलग संख्या।

उम्मीद है कि एक पर्याप्त प्रदर्शन है कि roundfकई दशमलव स्थानों के लिए उपयोग करने के लिए टूट गया है, और आप snprintfइसके बजाय का उपयोग करना चाहिए । यदि वह आपको एक भयानक हैक की तरह लगता है, तो शायद आप इस ज्ञान से आश्वस्त होंगे कि यह मूल रूप से सीपीथॉन क्या करता है


+1 जो मेरे उत्तर और उसके समान के साथ गलत हो जाता है के एक ठोस उदाहरण के लिए, IEEE फ़्लोटिंग पॉइंट की अजीबता के लिए धन्यवाद, और एक सीधा विकल्प प्रदान करता है। मैं परिधीय रूप से जागरूक था, काफी लंबे समय से, बहुत सारे प्रयास प्रिंट में डाल दिए और दोस्तों ने उन्हें राउंड-ट्रिपिंग फ्लोटिंग वैल्यू के लिए मुझे सुरक्षित किया। मुझे लगता है कि तब किया गया काम यहाँ दिखाई दे रहा होगा।
डेल हाग्लगंड ३ '’

अहम ... क्षमा करें शब्द सलाद के लिए अंत में वहाँ है, जो अब संपादित करने के लिए बहुत देर हो चुकी है। मेरे कहने का मतलब "" था ... बहुत सारे प्रयास प्रिंटफ में डाले गए और दोस्तों ने उन्हें सुरक्षित करने के लिए ... "
डेल हाग्लगंड

4

का उपयोग करें float roundf(float x)

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

#include <math.h>
float y = roundf(x * 100.0f) / 100.0f; 

आपके floatकार्यान्वयन के आधार पर , वे संख्याएँ जो आधी-अधूरी प्रतीत हो सकती हैं, नहीं हैं। फ्लोटिंग-पॉइंट आम तौर पर बेस -2 ओरिएंटेड होता है। इसके अलावा, 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.11 और 1.12 के बीच "1.115" "अर्ध-मार्ग" है, जब इसे रूपांतरित किया जाता है float, तो मान नहीं है 1.115000009537...और यह "अर्ध-मार्ग" नहीं है, लेकिन 1.12 के करीब है और निकटतम floatहै1.120000004768...

1. १.१२० "१.१२ और १.१३ के बीच" अर्ध-मार्ग "है, जब इसे रूपांतरित किया जाता है 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)

x बराबर 3.14 :)


यह छोटा है, लेकिन प्रश्न राउंडिंग का अनुरोध करता है। इसके अतिरिक्त, यह फ़्लोटिंग-पॉइंट ऑपरेशन्स में राउंडिंग त्रुटियों के अधीन है।
एरिक पोस्टपिसिल

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

-1 चार कारणों से: 1) स्पष्टीकरण की कमी, 2) बफर अतिप्रवाह की भेद्यता - यह अतिप्रवाह करेगा, और इसलिए संभवतः दुर्घटनाग्रस्त हो सकता है, अगर 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 से अधिक दशमलव स्थान शामिल हो सकते हैं (विभिन्न कारणों से; रखने के लिए कोई इष्टतम स्थान नहीं है ... विशिष्ट स्थितियों पर निर्भर करता है प्रत्येक प्रणाली का समर्थन करना चाहिए, जैसे छोटे आइटम जिनकी कीमतें हैं प्रति यूनिट एक पैसा के अंश हैं); और, फ़्लोटिंग पॉइंट कंप्यूटेशन उन मानों पर किए जाते हैं जहाँ परिणाम प्लस / माइनस एप्सिलॉन होते हैं। मैं इन मुद्दों का सामना कर रहा हूं और वर्षों से अपनी रणनीति तैयार कर रहा हूं। मैं यह दावा नहीं करूंगा कि मैंने हर परिदृश्य का सामना किया है या सबसे अच्छा जवाब दिया है, लेकिन नीचे मेरे दृष्टिकोण का एक उदाहरण है जो अब तक इन मुद्दों पर काबू पा लेता है:

मान लीजिए कि 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)अपेक्षित परिणाम देने के लिए फ़ंक्शन का कारण बनता है । इस मामले के लिए, अनुगामी 9s की कोई संख्या हो सकती है ।

के लिए val = 6.824999499999, परिणाम है 6.83। पहले कदम के रूप में 8 वें दशमलव स्थान पर गोलाई, यानी 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));

जहां N फ़्लोट्स / डबल्स पर सभी मध्यवर्ती गणनाओं के लिए बनाए रखने के लिए सटीक है। यह नकारात्मक मूल्यों पर भी काम करता है। मुझे नहीं पता कि यह दृष्टिकोण गणितीय रूप से सभी संभावनाओं के लिए सही है या नहीं।



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

यह फ्लोटिंग पॉइंट नंबर को इंट में छोड़ देता है, पॉइंट को लेफ्ट शिफ्ट करके और पांच से ज्यादा कंडीशन के लिए चेक करता है।

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