फ्लोट और डबल में क्या अंतर है?


420

मैंने दोहरे परिशुद्धता और एकल परिशुद्धता के बीच अंतर के बारे में पढ़ा है। हालांकि, ज्यादातर मामलों में, floatऔर doubleविनिमेय प्रतीत होता है, अर्थात एक या दूसरे का उपयोग परिणामों को प्रभावित नहीं करता है। क्या वास्तव में यह मामला है? फ़्लोट्स और डबल्स इंटरचेंजेबल कब होते हैं? उनके बीच क्या अंतर हैं?

जवाबों:


521

बहुत बड़ा फर्क।

जैसा कि नाम से ही स्पष्ट है, एक double2x की सटीकता है [1] । सामान्य तौर पर सटीक के 15 दशमलव अंक होते हैं, जबकि 7 होते हैं।floatdoublefloat

यहां बताया गया है कि अंकों की संख्या की गणना कैसे की जाती है:

double52 मंटिसा बिट्स + 1 छिपे हुए बिट: लॉग (2 53 ) 10 लॉग (10) = 15.95 अंक हैं

floatमें 23 मंटिसा बिट्स + 1 छिपा हुआ बिट है: लॉग (2 24 ) 10 लॉग (10) = 7.22 अंक

बार-बार गणना किए जाने पर यह सटीक हानि अधिक ट्रंकेशन त्रुटियों को जमा कर सकती है, जैसे

float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
    b += a;
printf("%.7g\n", b); // prints 9.000023

जबकि

double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
    b += a;
printf("%.15g\n", b); // prints 8.99999999999996

इसके अलावा, फ्लोट का अधिकतम मूल्य लगभग है 3e38, लेकिन डबल के बारे में है 1.7e308, इसलिए float"इन्फिनिटी" (यानी एक विशेष फ्लोटिंग-पॉइंट संख्या) का उपयोग करके doubleकुछ सरल की तुलना में बहुत अधिक आसानी से मारा जा सकता है, जैसे कि 60 के भाज्य की गणना करना।

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


बेशक, कभी-कभी, doubleपर्याप्त रूप से सटीक भी नहीं होता है, इसलिए हमारे पास कभी-कभी long double[1] (उपरोक्त उदाहरण मैक पर 9.000000000000000066 देता है), लेकिन सभी फ़्लोटिंग पॉइंट प्रकार राउंड-ऑफ त्रुटियों से ग्रस्त हैं , इसलिए यदि परिशुद्धता बहुत महत्वपूर्ण है (जैसे पैसा प्रसंस्करण) आपको intएक अंश वर्ग का उपयोग करना चाहिए ।


इसके अलावा, +=फ़्लोटिंग पॉइंट संख्याओं का योग करने के लिए उपयोग न करें , क्योंकि त्रुटियां जल्दी से जमा होती हैं। यदि आप पायथन का उपयोग कर रहे हैं, तो उपयोग करें fsum। अन्यथा, कहन सारांश एल्गोरिदम को लागू करने का प्रयास करें ।


[१]: सी और सी ++ मानकों के प्रतिनिधित्व को निर्दिष्ट नहीं करते हैं float, doubleऔर long double। यह संभव है कि तीनों को आईईईई डबल-परिशुद्धता के रूप में लागू किया जाए। फिर भी, अधिकांश आर्किटेक्चर (gcc, MSVC; x86, x64, ARM) के float लिए वास्तव में IEEE सिंगल-प्रिसिजन फ़्लोटिंग पॉइंट नंबर (बाइनरी 32) है, और double यह आईईईई डबल-प्रिसिजन फ़्लोटिंग पॉइंट नंबर (बाइनरी 64) है।


9
समन के लिए सामान्य सलाह यह है कि अपने फ्लोटिंग पॉइंट नंबरों को संक्षेपण से पहले परिमाण (सबसे छोटा) से क्रमबद्ध करें।
आर .. गिटहब स्टॉप हेल्पिंग ICE

ध्यान दें कि जबकि C / C ++ फ्लोट और डबल लगभग हमेशा IEEE सिंगल और डबल परिशुद्धता क्रमशः C / C ++ लॉन्ग डबल होता है जो आपके CPU, कंपाइलर और OS पर निर्भर करता है। कभी-कभी यह डबल के समान होता है, कभी-कभी यह कुछ सिस्टम-विशिष्ट विस्तारित प्रारूप होता है, कभी-कभी यह IEEE क्वाड सटीक होता है।
प्लग

@ R..GitHubSTOPHELPINGICE: क्यों? क्या आप समझाएँगे?
इनक्यूसिटिव

@ इनक्यूसिटिव: उदाहरण के लिए एक एरे पर विचार करें जिसमें मान 2 ^ 24 से युक्त हो और उसके बाद 2 ^ 24 मान का दोहराव हो। क्रम में Summing 2 ^ 24 पैदा करता है। पलटने से 2 ^ 25 पैदा होता है। बेशक आप उदाहरण बना सकते हैं (उदाहरण के लिए इसे 2 ^ 25 1 की पुनरावृत्ति बनाएं) जहां कोई भी आदेश समाप्त होता है एक एकल संचायक के साथ भयावह रूप से गलत है, लेकिन सबसे छोटा-परिमाण-सबसे अच्छा है। बेहतर करने के लिए आपको किसी प्रकार के पेड़ की आवश्यकता होती है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

56

यहाँ मानक C99 (ISO-IEC 9899 6.2.5 or10) या C ++ 2003 (ISO-IEC 14882-2003 3.1.9 )8) मानक क्या कहते हैं:

वहाँ तीन चल बिन्दु प्रकार हैं: float, double, और long double। प्रकार doubleकम से कम उतना सटीक प्रदान करता है float, और प्रकार long doubleकम से कम उतना सटीक प्रदान करता है double। प्रकार के मूल्यों का सेट प्रकार के मूल्यों के सेट का floatसबसेट है double; प्रकार के मूल्यों का doubleसमुच्चय प्रकार के मूल्यों के समुच्चय का उपसमूह है long double

C ++ मानक कहते हैं:

फ्लोटिंग-पॉइंट प्रकारों का मूल्य प्रतिनिधित्व कार्यान्वयन-परिभाषित है।

मैं सुझाव दूंगा कि उत्कृष्ट हर कंप्यूटर वैज्ञानिक को फ्लोटिंग-पॉइंट अंकगणित के बारे में क्या जानना चाहिए जो IEEE फ्लोटिंग-पॉइंट मानक को गहराई से कवर करता है। आप प्रतिनिधित्व विवरणों के बारे में जानेंगे और आप महसूस करेंगे कि परिमाण और परिशुद्धता के बीच एक व्यापार है। फ़्लोटिंग पॉइंट प्रतिनिधित्व की सटीकता बढ़ जाती है क्योंकि परिमाण कम हो जाता है, इसलिए -1 और 1 के बीच फ़्लोटिंग पॉइंट संख्याएं सबसे अधिक सटीक होती हैं।


27

द्विघात समीकरण को देखते हुए: x 2  -   4.0000000 x + 3.9999999 = 0, 10 महत्वपूर्ण अंकों की सटीक जड़ें हैं, r 1  = 2.000316228 और r 2  = 1.999683772।

का उपयोग कर floatऔर double, हम एक परीक्षण कार्यक्रम लिख सकते हैं:

#include <stdio.h>
#include <math.h>

void dbl_solve(double a, double b, double c)
{
    double d = b*b - 4.0*a*c;
    double sd = sqrt(d);
    double r1 = (-b + sd) / (2.0*a);
    double r2 = (-b - sd) / (2.0*a);
    printf("%.5f\t%.5f\n", r1, r2);
}

void flt_solve(float a, float b, float c)
{
    float d = b*b - 4.0f*a*c;
    float sd = sqrtf(d);
    float r1 = (-b + sd) / (2.0f*a);
    float r2 = (-b - sd) / (2.0f*a);
    printf("%.5f\t%.5f\n", r1, r2);
}   

int main(void)
{
    float fa = 1.0f;
    float fb = -4.0000000f;
    float fc = 3.9999999f;
    double da = 1.0;
    double db = -4.0000000;
    double dc = 3.9999999;
    flt_solve(fa, fb, fc);
    dbl_solve(da, db, dc);
    return 0;
}  

कार्यक्रम चलाना मुझे देता है:

2.00000 2.00000
2.00032 1.99968

ध्यान दें कि संख्याएं बड़ी नहीं हैं, लेकिन फिर भी आपको उपयोग करके रद्द करने के प्रभाव मिलते हैं float

(वास्तव में, ऊपर एकल या डबल-सटीक फ़्लोटिंग-पॉइंट संख्याओं का उपयोग करके द्विघात समीकरणों को हल करने का सबसे अच्छा तरीका नहीं है, लेकिन जवाब एक स्थिर विधि का उपयोग करने पर भी अपरिवर्तित रहता है ।)


19
  • एक डबल 64 और एकल परिशुद्धता (फ्लोट) 32 बिट्स है।
  • डबल में एक बड़ा मंटिसा (वास्तविक संख्या का पूर्णांक बिट) है।
  • कोई भी अशुद्धि दोहरी में छोटी होगी।

12

फ्लोट-पॉइंट गणना में शामिल संख्याओं का आकार सबसे अधिक प्रासंगिक नहीं है। यह गणना की जा रही है जो प्रासंगिक है।

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

परीक्षण विशेष रूप से उन नंबरों का उपयोग कर सकते हैं जो इस तरह की त्रुटि का कारण बनेंगे और इसलिए परीक्षण किया है कि आपने अपने कोड में उपयुक्त प्रकार का उपयोग किया है।


9

टाइप फ्लोट, 32 बिट्स, 7 अंको की सटीकता है। हालांकि यह बहुत बड़ी या बहुत छोटी श्रेणी (+/- 3.4 * 10 ^ 38 या * 10 ^ -38) के साथ मूल्यों को संग्रहीत कर सकता है, इसमें केवल 7 महत्वपूर्ण अंक हैं।

टाइप डबल, 64 बिट्स, की एक बड़ी रेंज (* 10 ^ + / - 308) और 15 अंक सटीक है।

टाइप डबल डबल नाममात्र 80 बिट्स है, हालांकि एक संकलक / ओएस युग्मन इसे संरेखण प्रयोजनों के लिए 12-16 बाइट्स के रूप में संग्रहीत कर सकता है। लंबे डबल में एक घातांक होता है जो केवल हास्यास्पद रूप से विशाल होता है और इसमें 19 अंक सटीक होना चाहिए। Microsoft, अपने अनंत ज्ञान में, लंबी डबल से 8 बाइट्स तक सीमित करता है, जो सादे डबल के समान है।

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



9

मैं बस एक त्रुटि में भाग गया, जिसने मुझे हमेशा पता लगाने के लिए लिया और संभावित रूप से आप फ्लोट सटीक का एक अच्छा उदाहरण दे सकते हैं।

#include <iostream>
#include <iomanip>

int main(){
  for(float t=0;t<1;t+=0.01){
     std::cout << std::fixed << std::setprecision(6) << t << std::endl;
  }
}

आउटपुट है

0.000000
0.010000
0.020000
0.030000
0.040000
0.050000
0.060000
0.070000
0.080000
0.090000
0.100000
0.110000
0.120000
0.130000
0.140000
0.150000
0.160000
0.170000
0.180000
0.190000
0.200000
0.210000
0.220000
0.230000
0.240000
0.250000
0.260000
0.270000
0.280000
0.290000
0.300000
0.310000
0.320000
0.330000
0.340000
0.350000
0.360000
0.370000
0.380000
0.390000
0.400000
0.410000
0.420000
0.430000
0.440000
0.450000
0.460000
0.470000
0.480000
0.490000
0.500000
0.510000
0.520000
0.530000
0.540000
0.550000
0.560000
0.570000
0.580000
0.590000
0.600000
0.610000
0.620000
0.630000
0.640000
0.650000
0.660000
0.670000
0.680000
0.690000
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999

जैसा कि आप 0.83 के बाद देख सकते हैं, परिशुद्धता काफी नीचे चला जाता है।

हालाँकि, अगर मैं tडबल सेट करता हूं, तो ऐसा कोई मुद्दा नहीं होगा।

इस छोटी सी त्रुटि को महसूस करने में मुझे पांच घंटे लगे, जिसने मेरे कार्यक्रम को बर्बाद कर दिया।


4
बस यह सुनिश्चित करने के लिए: आपके मुद्दे का समाधान अधिमानतः एक int का उपयोग करना चाहिए? यदि आप 100 बार पुनरावृति करना चाहते हैं, तो आपको
12-21 बजे

8
उपयोग करना doubleयहां अच्छा समाधान नहीं है। आप intअपने फ्लोटिंग-पॉइंट वैल्यू को प्राप्त करने के लिए आंतरिक गुणा करने के लिए गिनती और उपयोग करते हैं।
रिचर्ड

8

झूलों में युगल की तुलना में कम सटीकता होती है। यद्यपि आप पहले से ही जानते हैं, बेहतर समझ के लिए फ्लोटिंग-पॉइंट अंकगणित के बारे में हमें क्या जानना चाहिए


उदाहरण के लिए, सभी AVR युगल फ्लोट (चार-बाइट) हैं।
पीटर मोर्टेंसन

3

फ़्लोटिंग पॉइंट नंबरों का उपयोग करते समय आप भरोसा नहीं कर सकते कि आपके स्थानीय परीक्षण बिल्कुल उसी तरह होंगे जैसे कि सर्वर साइड पर किए गए परीक्षण। पर्यावरण और संकलक शायद आप स्थानीय प्रणाली पर भिन्न हैं और जहां अंतिम परीक्षण चलाए जाते हैं। मैंने इस समस्या को पहले भी कई बार TopCoder प्रतियोगिताओं में देखा है, खासकर यदि आप दो फ्लोटिंग पॉइंट संख्याओं की तुलना करने का प्रयास करते हैं।


3

अंतर्निहित तुलना संचालन अलग-अलग होता है जब आप फ्लोटिंग पॉइंट के साथ 2 नंबरों की तुलना करते हैं, तो डेटा प्रकार (यानी फ्लोट या डबल) में अंतर के परिणामस्वरूप अलग-अलग परिणाम हो सकते हैं।


1

यदि कोई एम्बेडेड प्रोसेसिंग के साथ काम करता है, तो अंतत: अंतर्निहित हार्डवेयर (जैसे FPGA या कुछ विशिष्ट प्रोसेसर / माइक्रोकंट्रोलर मॉडल) ने अस्थायी रूप से हार्डवेयर में कार्यान्वित किया होगा, जबकि डबल सॉफ्टवेयर रूटीन का उपयोग करेगा। इसलिए यदि फ्लोट की सटीकता जरूरतों को संभालने के लिए पर्याप्त है, तो प्रोग्राम फ्लोट के साथ कुछ समय तेजी से निष्पादित करेगा, फिर डबल। जैसा कि अन्य उत्तरों पर ध्यान दिया गया है, संचय त्रुटियों से सावधान रहें।


-1

एक int(पूरी संख्या) के विपरीत , floatएक दशमलव बिंदु है, और इसलिए एक कर सकते हैं double। लेकिन दोनों के बीच का अंतर यह है कि ए double, ए के मुकाबले दोगुना है float, जिसका अर्थ है कि दशमलव बिंदु के बाद इसकी संख्या दोगुनी हो सकती है।


4
इसका मतलब यह बिल्कुल नहीं है। इसका वास्तव में कई अभिन्न दशमलव अंकों से दोगुना है, और यह दोगुने से अधिक है। आंशिक अंकों और परिशुद्धता के बीच संबंध रैखिक नहीं है: यह मूल्य पर निर्भर करता है: उदाहरण के लिए 0.5 सटीक है, लेकिन 0.33333333333333333333 नहीं है।
लोर्ने के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.