2010-04-17 15 views
9

मैं संभव डेटा हानिडेटा हानि के बारे में चेतावनी C++/सी

के बारे में एक सौम्य चेतावनी C4244 चेतावनी हो रही है: 'नाव' को 'स्थिरांक पूर्णांक', डेटा

की संभावित हानि से रूपांतरण: 'तर्क'

प्रश्न

मुझे याद है के रूप में अगर नाव पूर्णांक तुलना में एक बड़ा सटीक है। तो यदि मैं एक छोटे डेटा प्रकार (int) से बड़े डेटा प्रकार (फ्लोट) में कनवर्ट करता हूं तो डेटा कैसे खोया जा सकता है?

+0

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

+1

@Neil: यह सीपीयू पर बहुत निर्भर करता है। कई आर्किटेक्चर हैं जहां फ्लोट डबल से नाटकीय रूप से तेज़ है। – jalf

+0

@jalf संभव है, लेकिन सी या सी ++ कोड में ज्यादातर स्थितियों में, फ्लोट को वैसे भी डबल्स में पदोन्नत किया जाएगा। –

उत्तर

14

क्योंकि float संख्याएं सटीक नहीं हैं। float का अधिकतम मूल्य float है, भले ही आप प्रत्येक संभावित मान का प्रतिनिधित्व नहीं कर सकते intfloat में हो सकता है, भले ही float का अधिकतम मूल्य बहुत अधिक हो।

#include <stdio.h> 

int main() 
{ 
for(int i = 0; i < 2147483647; i++) 
{ 
    float value = i; 
    int ivalue = value; 
    if(i != ivalue) 
    printf("Integer %d is represented as %d in a float\n", i, ivalue); 
} 
} 

आप जल्दी से हजारों पूर्णांकों का अरबों कि float रों के रूप में प्रतिनिधित्व नहीं किया जा सकता देखते हैं कि देखेंगे:

उदाहरण के लिए, इस साधारण प्रोग्राम चलाते हैं। उदाहरण के लिए, 16,777,21 9 और 16,777,221 के बीच सभी पूर्णांक 16,777,220 के रूप में दर्शाए जाते हैं।

संपादित करें फिर कि इस कार्यक्रम से ऊपर चल रहा है इंगित करता है 2.071.986.175सकारात्मक पूर्णांकों कि ठीक के रूप में float रों नहीं दर्शाया जा सकता देखते हैं कि। जो आपको लगभग 100 लाख सकारात्मक पूर्णांक के साथ मोटे तौर पर छोड़ देता है जो float में सही ढंग से फिट हो जाता है। इसका मतलब है कि से केवल एक पूर्णांक सही है जब आप इसे एक फ्लोट में डालते हैं।

मुझे उम्मीद है कि संख्याएं नकारात्मक पूर्णांक के लिए समान होंगी।

+0

@ ब्लू नवम्बर: प्रत्येक पूर्णांक> 2^24। – Stephen

+0

हजारों नहीं। अरबों। – slacker

+0

आपका कोड एक फ्लोट (बड़ा) से int (छोटा) में परिवर्तित करता है, इसलिए मुझे लगता है कि डेटा हानि संभव है। मेरा सवाल –

6

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

सिस्टम पर जहां int 32 बिट्स है, double आमतौर पर 64 बिट्स होता है और इसलिए किसी भी int का प्रतिनिधित्व कर सकता है।

3

दोनों प्रकार 4 बाइट्स (32 बिट्स) से बने होते हैं। उनमें से केवल एक अंश (फ्लोट) की अनुमति देता है।

इसे एक फ्लोट उदाहरण के लिए लें;

34,156

(पूर्णांक) (अंश)

अब आप अपने तर्क का उपयोग करें।; यदि उनमें से एक को अंश जानकारी को सहेजना चाहिए (इसके बाद इसे किसी संख्या का प्रतिनिधित्व करना चाहिए) तो इसका मतलब है कि इसमें पूर्णांक भाग के लिए कम बिट्स हैं।

इस प्रकार, एक फ्लोट एक अधिकतम पूर्णांक संख्या का प्रतिनिधित्व कर सकता है जो int की प्रकार क्षमता से छोटा है।

अधिक विशिष्ट होने के लिए, एक "int" एक पूर्णांक संख्या का प्रतिनिधित्व करने के लिए 32 बिट्स का उपयोग करता है (4,294,967,296 का अधिकतम हस्ताक्षरित पूर्णांक)। ऐसा करने के लिए "फ्लोट" 23 बिट्स का उपयोग करता है (8,388,608 का अधिकतम हस्ताक्षरित पूर्णांक)।

यही कारण है कि जब आप int से फ़्लोट में कनवर्ट करते हैं तो आप डेटा खो सकते हैं।

उदाहरण: पूर्णांक = 1.158.354.125

आप एक "फ्लोट" में इस संख्या की दुकान नहीं कर सकते हैं।

में और जानकारी यहां:

http://en.wikipedia.org/wiki/Single_precision_floating-point_format

http://en.wikipedia.org/wiki/Integer_%28computer_science%29

+0

कुछ कारणों से यह थोड़ा गलत है। उनमें से एक 'फ्लोट' है जिसमें मंटिसा के लिए 24 बिट हैं, 23 नहीं। इसलिए 16777216 तक प्रत्येक हस्ताक्षरित पूर्णांक बिल्कुल प्रतिनिधित्व योग्य है। – slacker

+0

मंटिसा के लिए कितने बिट्स डबल उपयोग करते हैं? –

+0

आईईईई 754 एकल फ्लोट में मंटिसा के 23 बिट हैं, जो 24 बिट्स की प्रभावी श्रृंखला प्रदान करते हैं क्योंकि एक्सपोनेंट सामान्यीकृत होता है। मंथिसा एक्सपोनेंट से "थोड़ा चुराता है"। –

0

एक float मानक आईईईई एकल परिशुद्धता प्रारूप में आम तौर पर है। इसका मतलब है कि float में केवल 24 बिट सटीक हैं, जबकि int 32-बिट होने की संभावना है। इसलिए, यदि आपके int में ऐसी संख्या है जिसका पूर्ण मूल्य 24 बिट्स में फिट नहीं हो सकता है, तो संभव है कि आप इसे निकटतम प्रतिनिधित्व करने योग्य संख्या में घुमाएंगे।

+0

नाइट: "प्रेसिजन" का एक मानक अर्थ है जो केवल संयोग से संख्यात्मक संख्या के सेट की सीमा से संबंधित है। "प्रेसिजन" सबसे छोटा सकारात्मक संख्या है जिसे 1.0 में जोड़ा जा सकता है और 1.0 से अलग संख्या उत्पन्न करता है। एक int की परिशुद्धता 1 है (एक बिट, 31 या 32 नहीं)। आईईईई 754 एकल फ्लोट की सटीकता लगभग 5.9 6e-8 (24 बिट्स) है। –

+0

@ जैव डैडसन: मैंने एक और आकस्मिक (गैर-औपचारिक) तरीके से "परिशुद्धता" शब्द का उपयोग किया। इस जवाब में यह स्पष्ट रूप से "महत्वपूर्ण बिट्स की संख्या" का मतलब था। – slacker

1

प्रेसिजन कोई फर्क नहीं पड़ता। Int की सटीकता 1 है, जबकि एक सामान्य फ्लोट (आईईईई 754 एकल परिशुद्धता) की सटीकता लगभग 5.9 6e-8 है। क्या मायने रखता है संख्याओं के सेट जो दो प्रारूपों का प्रतिनिधित्व कर सकते हैं। यदि ऐसी संख्याएं हैं जो int वास्तव में उस फ्लोट का प्रतिनिधित्व नहीं कर सकती हैं, तो डेटा का संभावित नुकसान हो सकता है।

फ्लोट्स और इनट्स आमतौर पर 32 बिट्स दोनों होते हैं, लेकिन इसकी गारंटी नहीं है। मान लीजिए कि यह आपकी मशीन पर मामला है, यह इस प्रकार है कि इंट मान होना चाहिए कि फ्लोट बिल्कुल प्रतिनिधित्व नहीं कर सकता है, क्योंकि स्पष्ट रूप से फ्लोट वैल्यू हैं जो int वास्तव में प्रतिनिधित्व नहीं कर सकते हैं। एक प्रारूप की सीमा दूसरे के उचित सुपर-सेट नहीं हो सकती है यदि दोनों प्रारूप कुशलतापूर्वक बिट्स का उपयोग करते हैं।

एक 32 बिट int प्रभावी ढंग से 31 बिट्स है जो संख्या के पूर्ण मूल्य के लिए कोड है। एक आईईईई 754 फ्लोट प्रभावी रूप से केवल 24 बिट्स है जो मंटिसा के लिए कोड (एक अंतर्निहित) है।

0

तथ्य यह है कि 32 बिट्स का उपयोग करके एक फ्लोट और एक int का प्रतिनिधित्व किया जाता है। पूर्णांक मान सभी 32 बिट्स का उपयोग करता है ताकि यह -2 से 2 -1 से संख्याओं को समायोजित कर सके। हालांकि, एक फ्लोट एक्सपोनेंट के लिए साइन ((0.0 एफ सहित) और 8 बिट्स के लिए 1 बिट का उपयोग करता है। साधन 32 - 9 = 23 बिट्स मंटिसा के लिए छोड़ दिया। हालांकि, फ्लोट मानता है कि अगर मंटिसा और एक्सपोनेंट शून्य नहीं है, तो मंटिसा 1 से शुरू होता है। इसलिए 32 के बजाए आपके पूर्णांक के लिए 24 बिट्स कम या कम हैं। हालांकि, क्योंकि इसे स्थानांतरित किया जा सकता है, यह और अधिक समायोजित करता है 2 पूर्णांक से अधिक।

A floating point uses a Sign, an eXponent, and a Mantissa 
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M 

An integer has a Sign, and a Mantissa 
S M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M 

तो, एक पूर्णांक जैसे:

1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 

एक नाव में फिट बैठता है, क्योंकि यह स्थानांतरित किया जा सकता:

1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 
|  |        | 
|  +---------+     +---------+ 
|     |        | 
v     v        v 
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M 
1     1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 

मैं तुम्हें प्रतिपादक क्योंकि मैं सबसे अक्सर दिखाई नहीं देते इसे कंप्यूटिंग में गलती करें, लेकिन यह 5 (या -5?) जैसा होना चाहिए क्योंकि मैंने 5 बिट्स द्वारा स्थानांतरित किया है (लेकिन आपको 128 जोड़ना या घटाना होगा ...)। यह आपको स्पष्ट रूप से दिखाता है कि यदि आपको 5 बिट्स द्वारा स्थानांतरित करना है, तो आप 5 निचले बिट्स खोने जा रहे हैं।

तो इस अन्य पूर्णांक को 2 बिट्स के खोने के साथ एक फ्लोट में परिवर्तित किया जा सकता है (यानी जब आप एक पूर्णांक में वापस परिवर्तित होते हैं, तो अंतिम दो बिट्स (11) शून्य (00) पर सेट होते हैं क्योंकि वे सहेजे नहीं गए थे फ्लोट):

1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 
|  |        |    | | | | | 
|  +---------+     +---------+  +-+-+-+-+--> all lost 
|     |        | 
v     v        v 
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M 
1     1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 

वास्तव में बहुत सरल सामान।

महत्वपूर्ण नोट: हाँ, पूर्णांक में पहला 1 संकेत है, तो अगले 1 को मंटिसा में कॉपी नहीं किया गया है, यह 1 माना जाता है इसलिए इसकी आवश्यकता नहीं है।

संबंधित मुद्दे