2008-11-20 2 views
7

में दशमलव मान को ट्रंकेट करें C++ float वैरिएबल को छोटा करने का सबसे आसान तरीका क्या है जिसका 0.6000002 का मान 0.6000 के मान पर है और इसे चर में वापस संग्रहीत करता है?सी ++

उत्तर

5

सबसे पहले यह जानना महत्वपूर्ण है कि फ़्लोटिंग पॉइंट नंबर अनुमानित हैं। @Greg Hewgill द्वारा प्रदान की गई लिंक को समझने के लिए यह समस्या पूरी तरह से हल करने योग्य नहीं है।

शायद बेहतर तरीका है, लेकिन कम कुशल:

char sz[64]; 
double lf = 0.600000002; 
sprintf(sz, "%.4lf\n", lf); //sz contains 0.6000 

double lf2 = atof(sz); 

//lf == 0.600000002; 
//lf2 == 0.6000 

printf("%.4lf", lf2); //print 0.6000 

अधिक कुशल तरीका है, लेकिन शायद कम सटीक

लेकिन यहाँ समस्या के समाधान की एक जोड़ी है कि शायद अपनी जरूरत को पूरा करेगा कर रहे हैं:

double lf = 0.600000002; 
int iSigned = lf > 0? 1: -1; 
unsigned int uiTemp = (lf*pow(10, 4)) * iSigned; //Note I'm using unsigned int so that I can increase the precision of the truncate 
lf = (((double)uiTemp)/pow(10,4) * iSigned); 
6

यथार्थ रूप से यह संभव नहीं है। यह सी ++ सीमा नहीं है, लेकिन जिस तरह से फ़्लोटिंग पॉइंट काम करता है। कई मूल्यों के लिए कोई सटीक प्रतिनिधित्व नहीं होता है, इसलिए आप आसानी से कई अंकों को कम नहीं कर सकते हैं।

प्रिंटफ प्रारूप तारों का उपयोग करके प्रिंट करते समय आप छंटनी कर सकते हैं।

यदि आपको वास्तव में केवल सीमित संख्या में अंकों को स्टोर करने में सक्षम होना चाहिए, तो मेरा सुझाव है कि आप इसके बजाय एक निश्चित-सटीक डेटा प्रकार का उपयोग करें।

12

के लिए एक अच्छा संदर्भ यह होता है डेविड गोल्डबर्ग द्वारा What Every Computer Scientist Should Know About Floating Point Arithmetic में पाया जा सकता है।

+0

लिंक ग्रेग पोस्ट करने के लिए धन्यवाद, मैं उस सही दस्तावेज़ के बारे में सोच रहा था जब मैंने अपना जवाब लिखा लेकिन मेरे जीवन के लिए मुझे शीर्षक याद नहीं आया। –

3

मुझे लगता है कि यहां सवाल पूछा जाना चाहिए: आपको इसे छोटा करने की आवश्यकता क्यों है?

यदि मूल्यों के बीच तुलना के लिए, तो आपको ईपीएसलॉन परीक्षण का उपयोग करने पर विचार करना चाहिए। (आपके मामले में अतिरिक्त सहिष्णुता मूल्य के साथ, क्योंकि यह आम तौर पर स्वीकार किए गए ईपीएसलॉन से कहीं अधिक बड़ा लगता है)।

यदि आप इसे 0.6000 के रूप में प्रिंट करना चाहते हैं, तो दूसरों द्वारा सुझाए गए तरीकों का उपयोग करें।

1
roundf(myfloat * powf(10, numDigits))/powf(10, numDigits); 

उदाहरण के लिए, आपके मामले में आप तीन अंकों (numDigits) को छोटा कर रहे हैं। आप उपयोग करेंगे:

roundf(0.6000002 * 1000)/1000 
// And thus: 
roundf(600.0002)/1000 
600/1000 
0.6 

(आप शायद powf का परिणाम कहीं, स्टोर के बाद से आप इसे दो बार का उपयोग कर रहे हैं।)

कारण कैसे तैरता सामान्य रूप से कंप्यूटर पर जमा हो जाती है, वहाँ था करने के लिए शायद त्रुटिपूर्णता हो। हालांकि, फ्लोट्स का उपयोग करने के लिए आपको यही मिलता है।

1

उपयोग करें:

floor(0.6000002*10000)/10000 
0

यहाँ अन्य उत्तर में सलाह और इसके उपयोग का एक उदाहरण का उपयोग करते हुए एक समारोह है:

#include <iostream> 
#include <cmath> 

static void Truncate(double& d, unsigned int numberOfDecimalsToKeep); 

int main(int, char*[]) 
{ 

    double a = 1.23456789; 
    unsigned int numDigits = 3; 

    std::cout << a << std::endl; 

    Truncate(a,3); 

    std::cout << a << std::endl; 

    return 0; 
} 

void Truncate(double& d, unsigned int numberOfDecimalsToKeep) 
{ 
    d = roundf(d * powf(10, numberOfDecimalsToKeep))/powf(10, numberOfDecimalsToKeep); 
} 
0

अन्य उत्तर की तरह, लेकिन आप उस दौर को भूल नहीं होना चाहिए , फर्श और trunc परिभाषा से अलग हैं।परिभाषा और निम्न में से उत्पादन उदाहरण देखें:

http://www.cplusplus.com/reference/cmath/trunc/

इस मामले में हम 4 दशमलव की एक परिशुद्धता के साथ trucate करने और गैर महत्वपूर्ण दशमलव से छुटकारा पाने की जरूरत है:

trunc(valueToTrunc*10000)/10000 

या

value = (double)((int)(valueToTrunc*10000))/(double)10000 
0

के लिए सी ++ 11 आप std::round हैडर <cmath> में परिभाषित का उपयोग कर सकते हैं:

auto trunc_value = std::round(value_to_trunc * 10000)/10000;