दिलचस्प पोस्ट
एक स्ट्रिंग के दूसरे स्ट्रिंग के साथ बदलें मैं ActiveRecord कॉलबैक चलाने से कैसे बच सकता हूं? मैं आईई में पृष्ठभूमि-आकार का काम कैसे करूं? पाठ फ़ाइल जावा में विशाल डेटा लिखने का सबसे तेज़ तरीका विंडोज स्टार्टअप पर सी # एप्लिकेशन को चलाने के लिए कैसे? क्या जीसीसी का __डेटाइट __ ((पैक किया गया है) / # प्रगामा पैक असुरक्षित है? कर्ल के साथ PHP में SOAP अनुरोध पायथन सूची चर परिवर्तन को प्रतिबिंबित नहीं करती है मैं तारों की ठीक तरह से तुलना कैसे करूं? AngularJS यूआरएल से टुकड़ा पहचानकर्ता को निकालना (# प्रतीक) सीएसएस को शामिल करने का सर्वोत्तम तरीका? @import का उपयोग क्यों करें? क्रमांतरण – संख्याओं के सभी संभव सेट मैं एसवीएन के साथ एक निर्देशिका को कैसे अनदेखा कर सकता हूं? Google Maps API को क्रॉस-डोमेन AJAX कॉल कैसे करें? क्या मैं अपने आवेदन में 'होम' बटन को ओवरराइड कर सकता हूं?

छोटी संभव राशि से एक अजगर फ़्लोटिंग बिंदु मूल्य बढ़ाएं

मैं शब्दकोश कुंजी के रूप में अस्थायी बिंदु मूल्यों का उपयोग कर रहा हूँ

कभी-कभी, बहुत बार कभी (और शायद कभी नहीं, लेकिन निश्चित रूप से कभी नहीं), टकराव हो जाएगा मैं फ्लोटिंग प्वाइंट वेल्यू को जितना संभव हो उतनी छोटी राशि के रूप में बढ़ाकर इनका हल करना चाहता हूं। मैं यह कैसे कर सकता हूँ?

सी में, मैं इसे हासिल करने के लिए मंटिसा के बिट्स को पीछे छोड़ दूंगा, लेकिन मुझे लगता है कि अजगर में संभव नहीं है।

वेब के समाधान से एकत्रित समाधान "छोटी संभव राशि से एक अजगर फ़्लोटिंग बिंदु मूल्य बढ़ाएं"

छोटी संभव राशि से एक अजगर फ़्लोटिंग बिंदु मूल्य बढ़ाएं

आप पागल नहीं हैं और आपको ऐसा करने में सक्षम होना चाहिए। यह अजगर गणित पुस्तकालय की एक वर्तमान कमी है, दुख की बात है, दोनों पायथन 2. एक्स और पायथन 3000 में। एक math.nextafter(x,y) होना चाहिए। math.nextafter(x,y) पायथन में लेकिन वहां नहीं है। यह जोड़ने के लिए तुच्छ होना होगा क्योंकि अधिकांश सी कंपलर के पास फ़ंक्शन हैं I

अगली (x, y) फ़ंक्शंस , y के दिशा में एक्स के बाद अगले अनुचित रूप से भिन्न प्रतिनिधित्व योग्य फ़्लोटिंग-पॉइंट वैल्यू वापस लेते हैं । अगली बार () फ़ंक्शंस प्लेटफार्म पर काम करने के लिए गारंटीकृत है या यह इंगित करने के लिए एक उचित मूल्य वापस करने के लिए कि अगले मान संभव नहीं है।

nextafter() फ़ंक्शंस POSIX और ISO C99 मानकों का हिस्सा हैं और दृश्य सी में _nextafter () है C99 अनुरूप मानक गणित पुस्तकालयों, दृश्य सी, सी ++, बूस्ट और जावा सभी आईईईई को लागू करने के बाद अगली () कार्य या विधियां (मैं ईमानदारी से नहीं जानता कि यदि .NET के पास है ()। माइक्रोसॉफ्ट C99 या POSIX के बारे में ज्यादा परवाह नहीं करता है।)

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

यहां कोई भी बिट विचलन कार्य नहीं है , जो कि किनारे मामलों से पूरी तरह से या सही तरीके से काम करते हैं, जैसे कि मूल्य 0.0, नकारात्मक 0.0, उपनिरपेक्ष, असंतुलन, ऋणात्मक मूल्य, ओवर या अंडरफ्लो आदि के चलते हैं । यहाँ सी में अगले () संदर्भ का एक कार्यान्वयन है अगर यह आपकी दिशा है तो सही बिट घुमाव कैसे करें

nextafter() या अन्य बाहर किए गए POSIX गणित फ़ंक्शन को प्राप्त करने के लिए दो ठोस काम के आसपास हैं:

नम्पी का प्रयोग करें:

 >>> import numpy >>> numpy.nextafter(0,1) 4.9406564584124654e-324 >>> numpy.nextafter(.1, 1) 0.10000000000000002 >>> numpy.nextafter(1e6, -1) 999999.99999999988 >>> numpy.nextafter(-.1, 1) -0.099999999999999992 

सीधे सिस्टम गणित DLL से लिंक करें:

 import ctypes import sys from sys import platform as _platform if _platform == "linux" or _platform == "linux2": _libm = ctypes.cdll.LoadLibrary('libm.so.6') _funcname = 'nextafter' elif _platform == "darwin": _libm = ctypes.cdll.LoadLibrary('libSystem.dylib') _funcname = 'nextafter' elif _platform == "win32": _libm = ctypes.cdll.LoadLibrary('msvcrt.dll') _funcname = '_nextafter' else: # these are the ones I have access to... # fill in library and function name for your system math dll print "Platform", repr(_platform), "is not supported" sys.exit(0) _nextafter = getattr(_libm, _funcname) _nextafter.restype = ctypes.c_double _nextafter.argtypes = [ctypes.c_double, ctypes.c_double] def nextafter(x, y): "Returns the next floating-point number after x in the direction of y." return _nextafter(x, y) assert nextafter(0, 1) - nextafter(0, 1) == 0 assert 0.0 + nextafter(0, 1) > 0.0 

और अगर आप वास्तव में एक शुद्ध पायथन समाधान चाहते हैं:

 # handles edge cases correctly on MY computer # not extensively QA'd... import math # 'double' means IEEE 754 double precision -- c 'double' epsilon = math.ldexp(1.0, -53) # smallest double that 0.5+epsilon != 0.5 maxDouble = float(2**1024 - 2**971) # From the IEEE 754 standard minDouble = math.ldexp(1.0, -1022) # min positive normalized double smallEpsilon = math.ldexp(1.0, -1074) # smallest increment for doubles < minFloat infinity = math.ldexp(1.0, 1023) * 2 def nextafter(x,y): """returns the next IEEE double after x in the direction of y if possible""" if y==x: return y #if x==y, no increment # handle NaN if x!=x or y!=y: return x + y if x >= infinity: return infinity if x <= -infinity: return -infinity if -minDouble < x < minDouble: if y > x: return x + smallEpsilon else: return x - smallEpsilon m, e = math.frexp(x) if y > x: m += epsilon else: m -= epsilon return math.ldexp(m,e) 

या, मार्क डिकिन्सन का उत्कृष्ट समाधान का उपयोग करें

स्पष्ट रूप से नीची समाधान सबसे आसान है

सबसे पहले, यह "टक्कर का जवाब" एक बहुत बुरा विचार है

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

आपके "हैश जांच" एल्गोरिथ्म को टक्कर हल करने के लिए एक से अधिक "लघु वेतन वृद्धि" के माध्यम से लूप करना होगा।

और अनुक्रमिक हैश जांच अक्षम होने के लिए जाना जाता है।

इसे पढ़ें: http://en.wikipedia.org/wiki/Quadratic_probing

दूसरा, mantissa और exponent के साथ अलग से sys.float_info.epsilon math.frexp और sys.float_info.epsilon का उपयोग करें।

 >>> m, e = math.frexp(4.0) >>> (m+sys.float_info.epsilon)*2**e 4.0000000000000018 
 import sys >>> sys.float_info.epsilon 2.220446049250313e-16 

मैं यह सोचने की सलाह देता हूं कि फ्लोट्स (या टाइमस्टैम्प) अद्वितीय होगा यदि सभी संभव है अद्वितीय आइडेंटिफ़ायर जारी करने के लिए एक गिनती इटरेटर, डेटाबेस अनुक्रम या अन्य सेवा का उपयोग करें।

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

भूलते हुए कि हम एक पल के लिए फ्लोटिंग पॉइंट वैल्यू क्यों बढ़ाना चाहते हैं, मुझे यह कहना होगा कि मुझे लगता है कि ऑटोप्लेटेड का अपना जवाब शायद सही है।

लेकिन समस्या डोमेन के लिए, मैं कई कुंजीपटल के रूप में फ़्लोट्स का उपयोग करने के विचार के लिए अधिकांश उत्तरदाताओं का गलतफहमी साझा करता हूं अगर दशमलव (मुख्य टिप्पणियों में प्रस्तावित) का उपयोग करने की आपत्ति यह है कि यह एक "हेवीवेट" समाधान है, मैं इसे स्वयं-समझौता करने का सुझाव देता हूं: यह देखें कि टाइमस्टैम्प पर व्यावहारिक प्रस्ताव क्या है, कई अंक उठाएं पर्याप्त रूप से इसे कवर करने के लिए, फिर आवश्यक राशि से सभी टाइमस्टैम्प गुणा करें ताकि आप चार्जर्स के रूप में पूर्णांक का उपयोग कर सकें। यदि आप टाइमर परिशुद्धता से परे एक अतिरिक्त अंक या दो खरीद सकते हैं, तो आप और भी आश्वस्त हो सकते हैं कि कोई भी कम टकराव नहीं होगा, और यदि टकराव हो, तो आप 1 को जोड़ सकते हैं अगले चल बिन्दु मूल्य)।

एक बेहतर जवाब (अब मैं बस मस्ती के लिए यह कर रहा हूँ …), बिट्स twiddling द्वारा प्रेरित। नकारात्मक मूल्यों की संख्या के हिस्सों के बीच ले जाने और अतिप्रवाह को संभालने में कुछ मुश्किल है।

 import struct def floatToieee754Bits(f): return struct.unpack('<Q', struct.pack('<d', f))[0] def ieee754BitsToFloat(i): return struct.unpack('<d', struct.pack('<Q', i))[0] def incrementFloat(f): i = floatToieee754Bits(f) if f >= 0: return ieee754BitsToFloat(i+1) else: raise Exception('f not >= 0: unsolved problem!') 

अपने फ्लोट टाइमस्टैम्प को संशोधित करने के बजाय, प्रत्येक मार्क के लिए एक ट्यूपल का उपयोग करें, क्योंकि मार्क रेन्सॉम ने सुझाव दिया है कि जहां ट्यूपल (x,y) x=your_unmodified_time_stamp और y=(extremely unlikely to be a same value twice)

इसलिए:

  1. x बस अनधिकृत टाइमस्टैम्प है और कई बार समान मूल्य हो सकता है;
  2. आप उपयोग कर सकते हैं:
    1. एक बड़ी श्रेणी से एक यादृच्छिक पूर्णांक संख्या,
    2. सीरियल पूर्णांक (0,1,2, आदि),
    3. यूयूआईडी

जबकि 2.1 (बड़ी रेंज से यादृच्छिक इंटेल) ईथरनेट के लिए बहुत अच्छा काम करता है, मैं 2.2 (सीरियलइज़र) या 2.3 (यूयूआईडी) का उपयोग करूँगा। आसान, तेज, बुलेटप्रूफ 2.2 और 2.3 के लिए आपको टक्कर का पता लगाने की भी ज़रूरत नहीं है (आप ईथरनेट के रूप में भी 2.1 के लिए इसे प्राप्त करना चाहते हैं।)

2.2 का फायदा यह है कि आप एक ही फ्लोट टाइम स्टाम्प के बारे में बता सकते हैं, और क्रमबद्ध, डेटा तत्व भी कर सकते हैं।

तो बस किसी भी सॉर्टिंग प्रकार के ऑपरेशन के लिए ट्यूपल से x निकालें और ट्यूपल ही हैश / डिक्शनरी के लिए टकराव मुक्त कुंजी है

संपादित करें

मुझे लगता है उदाहरण कोड में मदद मिलेगी:

 #!/usr/bin/env python import time import sys import random #generator for ints from 0 to maxinteger on system: serializer=(sn for sn in xrange(0,sys.maxint)) #a list with guranteed collisions: times=[] for c in range(0,35): t=time.clock() for i in range(0,random.choice(range(0,4))): times.append(t) print len(set(times)), "unique items in a list of",len(times) #dictionary of tuples; no possibilities of collisions: di={} for time in times: sn=serializer.next() di[(time,sn)]='Element {}'.format(sn) #for tuples of multiple numbers, Python sorts # as you expect: first by t[0] then t[1], until t[n] for key in sorted(di.keys()): print "{:>15}:{}".format(key, di[key]) 

आउटपुट:

 26 unique items in a list of 55 (0.042289, 0):Element 0 (0.042289, 1):Element 1 (0.042289, 2):Element 2 (0.042305, 3):Element 3 (0.042305, 4):Element 4 (0.042317, 5):Element 5 # and so on until Element n... 

कुंजी को टकराने के लिए, जोड़ें: के / 2 50


दिलचस्प समस्या जिस राशि को आप स्पष्ट रूप से जोड़ना चाहते हैं, वह पलायन मूल्य की भयावहता पर निर्भर करता है, ताकि सामान्यीकृत जोड़ केवल कम से कम महत्वपूर्ण बिट को प्रभावित करेगा।

यह जोड़ा जा सकता है कि सबसे छोटा मूल्य निर्धारित करने के लिए आवश्यक नहीं है। आपको यह करने की ज़रूरत लगभग है एफपीयू प्रारूप 52 मिंटिसा बिट्स और एक छिपी बिट प्रदान करता है, जो कि 53 बिट सटीक है। परिशुद्धता के इस स्तर के पास कहीं भी भौतिक स्थिरता नहीं है। कोई संवेदक इसके पास कुछ भी सक्षम उपाय नहीं है। तो आपके पास एक कठिन समस्या नहीं है

ज्यादातर मामलों में, कुंजी के लिए , आप उस 52-बिट अंश और छिपे हुए बिट के कारण , के / 2 53 को जोड़ सकते हैं।

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

तो मैं कहूंगा, कुंजी को टकराने के लिए, बस के / 2 50 जोड़ें और इसे एक दिन बुलाओ। 1


1. संभवत: एक से अधिक बार जब तक यह किसी भी शैतानी इकाई परीक्षण लेखकों को कम करने के लिए कम से कम किसी भी टकराने की कोशिश नहीं करता।

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

 while toInsert.key in myDict: # assumed to be positive toInsert.key *= 1.000000000001 myDict[toInsert.key] = toInsert 

उसने कहा कि आप संभवत: टाइमस्टैंप को चाबियों के रूप में इस्तेमाल नहीं करना चाहते हैं

कुंजी बदलकर टकरावों को हल करने के बजाय, कैसे टकराव इकट्ठा करने के बारे में? अर्थात:

 bag = {} bag[1234.] = 'something' 

हो जाता है

 bag = collections.defaultdict(list) bag[1234.].append('something') 

क्या इससे काम हो जायेगा?

यहां इसका हिस्सा है यह गंदा और धीमा है, लेकिन हो सकता है कि आपको यह पसंद है। यह कई कोने के मामलों में लापता है, लेकिन हो सकता है कि यह किसी और को बंद हो।

विचार एक अस्थायी बिंदु संख्या के हेक्स स्ट्रिंग प्राप्त करना है यह आपको दो प्रकार के झुकाव और झांकते हुए बिट्स के साथ एक स्ट्रिंग देता है। Twiddling एक दर्द है, क्योंकि आपको मैन्युअल रूप से सभी करना होगा और स्ट्रिंग्स से / में परिवर्तित करना होगा। वैसे भी, आप सकारात्मक (नकारात्मक) संख्याओं के लिए पिछले अंकों से (घटाएं) 1 को जोड़ते हैं। सुनिश्चित करें कि आप एक्सपोनेंट तक ले जाते हैं यदि आप अतिप्रवाह नकारात्मक संख्याएं थोड़ा अधिक मुश्किल होती हैं ताकि आप किसी भी बिट को बर्बाद न करें।

 def increment(f): h = f.hex() # decide if we need to increment up or down if f > 0: sign = '+' inc = 1 else: sign = '-' inc = -1 # pull the string apart h = h.split('0x')[-1] h,e = h.split('p') h = ''.join(h.split('.')) h2 = shift(h, inc) # increase the exponent if we added a digit h2 = '%s0x%s.%sp%s' % (sign, h2[0], h2[1:], e) return float.fromhex(h2) def shift(s, num): if not s: return '' right = s[-1] right = int(right, 16) + num if right > 15: num = right // 16 right = right%16 elif right < 0: right = 0 num = -1 else: num = 0 # drop the leading 0x right = hex(right)[2:] return shift(s[:-1], num) + right a = 1.4e4 print increment(a) - a a = -1.4e4 print increment(a) - a a = 1.4 print increment(a) - a 

ऑटोपॉपुलेटेड के उत्तर को देखने के बाद मुझे थोड़ा अलग जवाब मिला:

 import math, sys def incrementFloatValue(value): if value == 0: return sys.float_info.min mant, exponent = math.frexp(value) epsilonAtValue = math.ldexp(1, exponent - sys.float_info.mant_dig) return math.fsum([value, epsilonAtValue]) 

अस्वीकरण: मैं वास्तव में गणित में उतना ही महान नहीं हूं जितना मुझे लगता है;) कृपया इसे सत्यापित करने से पहले यह सही है कि यह प्रयोग करें। इसके अलावा मैं प्रदर्शन के बारे में निश्चित नहीं हूँ

कुछ नोट्स:

  • epsilonAtValue गणना करता है कि epsilonAtValue लिए कितने बिट्स का उपयोग किया जाता है (एक्सपोनेंट के लिए उपयोग की जाने वाली अधिकतम माइनस)।
  • मुझे यकीन नहीं है कि math.fsum() की आवश्यकता है, लेकिन हे यह दुख की बात नहीं लगती।

यह पता चला है कि यह वास्तव में बहुत जटिल है (हो सकता है कि सात लोगों ने अभी तक जवाब देने के बिना उत्तर दिया है …)

मुझे लगता है कि यह सही समाधान है, यह निश्चित रूप से 0 और सकारात्मक मूल्यों को सही ढंग से संभालना लगता है:

 import math import sys def incrementFloat(f): if f == 0.0: return sys.float_info.min m, e = math.frexp(f) return math.ldexp(m + sys.float_info.epsilon / 2, e)