ActiveRecord में फ्लोट बनाम दशमलव


283

कभी-कभी, एक्टिवरकॉर्ड डेटा प्रकार मुझे भ्रमित करते हैं। इर, अक्सर। मेरे शाश्वत प्रश्नों में से एक, एक दिए गए मामले के लिए है,

क्या मुझे उपयोग करना चाहिए :decimalया :float?

मैं अक्सर इस लिंक पर आता हूं, ActiveRecord:: दशमलव बनाम: फ्लोट? , लेकिन उत्तर मेरे लिए कुछ स्पष्ट होने के लिए पर्याप्त स्पष्ट नहीं हैं:

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

यहाँ कुछ उदाहरण मामले हैं:

  • जियोलोकेशन / अक्षांश / देशांतर: -45.756688, 120.5777777, ...
  • अनुपात / प्रतिशत: 0.9, 1.25, 1.333, 1.4143, ...

मैंने :decimalअतीत में उपयोग किया है, लेकिन मैंने पाया BigDecimalकि रूबी में एक फ्लोट की तुलना में रूबी अनावश्यक रूप से अजीब थी। मुझे यह भी पता है कि मैं :integerउदाहरण के लिए धन / सेंट का प्रतिनिधित्व करने के लिए उपयोग कर सकता हूं , लेकिन यह अन्य मामलों के लिए बिल्कुल फिट नहीं है, उदाहरण के लिए जब मात्रा जिसमें सटीक समय के साथ बदल सकता है।

  • प्रत्येक का उपयोग करने के फायदे / नुकसान क्या हैं?
  • किस प्रकार का उपयोग करना है, यह जानने के लिए अंगूठे के कुछ अच्छे नियम क्या होंगे?

जवाबों:


427

मुझे अपने CompSci प्रोफेसर को याद है कि मुद्रा के लिए कभी भी फ्लोट का उपयोग नहीं करना चाहिए।

इसका कारण यह है कि कैसे IEEE विनिर्देश बाइनरी प्रारूप में तैरता है। असल में, यह एक फ्लोट का प्रतिनिधित्व करने के लिए हस्ताक्षर, अंश और घातांक को संग्रहीत करता है। यह बाइनरी के लिए एक वैज्ञानिक संकेतन जैसा है (कुछ ऐसा +1.43*10^2)। उस वजह से, फ्लोट में बिल्कुल भिन्न और दशमलव को स्टोर करना असंभव है।

इसलिए एक दशमलव स्वरूप है। अगर तुम यह करते हो:

irb:001:0> "%.47f" % (1.0/10)
=> "0.10000000000000000555111512312578270211815834045" # not "0.1"!

जबकि अगर तुम बस करो

irb:002:0> (1.0/10).to_s
=> "0.1" # the interprer rounds the number for you

इसलिए यदि आप छोटे अंशों के साथ काम कर रहे हैं, जैसे चक्रवृद्धि ब्याज, या शायद जियोलोकेशन भी, तो मैं दशमलव प्रारूप की अत्यधिक अनुशंसा करूंगा, क्योंकि दशमलव प्रारूप 1.0/10बिल्कुल 0.1 है।

हालांकि, यह ध्यान दिया जाना चाहिए कि कम सटीक होने के बावजूद, फ्लोट को तेजी से संसाधित किया जाता है। यहाँ एक बेंचमार्क है:

require "benchmark" 
require "bigdecimal" 

d = BigDecimal.new(3) 
f = Float(3)

time_decimal = Benchmark.measure{ (1..10000000).each { |i| d * d } } 
time_float = Benchmark.measure{ (1..10000000).each { |i| f * f } }

puts time_decimal 
#=> 6.770960 seconds 
puts time_float 
#=> 0.988070 seconds

उत्तर

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

दशमलव का उपयोग करें यदि आप उन संख्याओं के साथ काम कर रहे हैं जो सटीक होने की आवश्यकता है और सही संख्या तक योग करें (जैसे चक्रवृद्धि ब्याज और धन-संबंधित चीजें)। याद रखें: यदि आपको सटीकता की आवश्यकता है, तो आपको हमेशा दशमलव का उपयोग करना चाहिए।


तो अगर मैं सही तरीके से समझूं, तो फ़्लोट बेस -2 में है जबकि दशमलव बेस -10 में है? फ्लोट के लिए एक अच्छा उपयोग क्या होगा? आपका उदाहरण क्या करता है, और प्रदर्शित करता है?
जोनाथन अलार्ड

1
आप के +1.43*2^10बजाय मतलब नहीं है +1.43*10^2?
कैमरून मार्टिन

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

1
@adg सही है: bigdecimal भी मुद्रा के लिए एक खराब विकल्प है।
एरिक डुमिनील

1
@ आप सही कह रहे हैं। मैं पिछले कुछ वर्षों में कुछ लेखांकन और वित्तीय अनुप्रयोगों के साथ काम कर रहा हूं और हम अपने सभी मुद्रा क्षेत्रों को पूर्णांक स्तंभों में संग्रहीत करते हैं। यह इस मामलों के लिए अधिक सुरक्षित है।
गिलहर्मे लेगो सैंटोस

19

रेल्स 3.2.18 में: दशमलव SQLServer का उपयोग करते समय पूर्णांक में बदल जाता है, लेकिन यह SQLite में ठीक काम करता है। पर स्विच करना: फ्लोट ने हमारे लिए इस समस्या को हल किया।

सबक सीखा है "हमेशा सजातीय विकास और तैनाती डेटाबेस का उपयोग करें!"


3
अच्छी बात है, रेल करने के 3 साल बाद, मैं तहे दिल से सहमत हूं।
जोनाथन एलार्ड

3
"हमेशा सजातीय विकास और तैनाती डेटाबेस का उपयोग करें!"
zx1986

15

4.1.0 रेल में, मैंने MySql डेटाबेस के लिए अक्षांश और देशांतर को बचाने के साथ समस्या का सामना किया है। यह फ्लोट डेटा प्रकार के साथ बड़े अंश संख्या को नहीं बचा सकता है। और मैं डेटा प्रकार को दशमलव और मेरे लिए काम करने के लिए बदल देता हूं।

  परिवर्तन बदलें
    change_column: शहर,: अक्षांश, दशमलव,: परिशुद्धता => 15,: स्केल => 13
    change_column: शहर, देशांतर, दशमलव,: परिशुद्धता => 15,: स्केल => 13
  समाप्त

मैं अपने: अक्षांश और: देशांतर को पोस्टग्रेज में तैरते हुए बचाता हूं, और यह ठीक काम करता है।
स्कॉट डब्ल्यू

3
@ रोबिकुल: हाँ, यह अच्छा है, लेकिन ओवरकिल। decimal(13,9) अक्षांश और देशांतर के लिए पर्याप्त है। @ScottW: मुझे याद नहीं है, लेकिन अगर Postgres IEEE फ़्लोट्स का उपयोग करते हैं, तो यह केवल "ठीक काम करता है" क्योंकि आप समस्याओं में नहीं भागे हैं ... YET। यह अक्षांश और देशांतर के लिए एक अपर्याप्त प्रारूप है। Yo में अंततः कम से कम महत्वपूर्ण अंकों में त्रुटियां होंगी।
लोनी एवरीस

@LonnyEachus IEEE फ़्लोट्स को lat / longs के लिए अपर्याप्त बनाता है?
अलेक्जेंडर सुरफेल

3
@AlexanderSuraphel यदि आप दशमलव अक्षांश और देशांतर का उपयोग कर रहे हैं, तो एक IEEE फ़्लोट कम से कम महत्वपूर्ण अंकों में त्रुटियों के लिए अतिसंवेदनशील है। उदाहरण के लिए आपके अक्षांश और देशांतर में 1 मीटर की शुद्धता हो सकती है, लेकिन आपके पास 100 मीटर या उससे अधिक की त्रुटियां हो सकती हैं। यह विशेष रूप से सच है यदि आप गणना में उनका उपयोग कर रहे हैं।
लोनी एरीस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.