फ्लोटिंग-पॉइंट में दो संख्याओं के माध्य की गणना?


15

आज्ञा देना x, yदो फ़्लोटिंग पॉइंट नंबर हो। उनके माध्य की गणना करने का सही तरीका क्या है?

भोलेपन के (x+y)/2परिणामस्वरूप बहुत अधिक हो सकते हैं xऔर yबहुत बड़े होते हैं। मुझे लगता है कि 0.5 * x + 0.5 * yशायद बेहतर है, लेकिन इसमें दो गुणा शामिल हैं (जो शायद अक्षम है), और मुझे यकीन नहीं है कि यह पर्याप्त अच्छा है। क्या कोई बेहतर तरीका है?

एक और विचार है कि मैं साथ खेल रहा हूँ (y/2)(1 + x/y)अगर x<=y। लेकिन फिर, मुझे यकीन नहीं है कि इसका विश्लेषण कैसे करें और साबित करें कि यह मेरी आवश्यकताओं को पूरा करता है।

इसके अलावा, मुझे एक गारंटी की आवश्यकता है कि गणना का मतलब होगा >= min(x,y)और <= max(x,y)। जैसा कि डॉन हैच के जवाब में बताया गया है , शायद इस प्रश्न को प्रस्तुत करने का एक बेहतर तरीका है: दो संख्याओं के अर्थ का कार्यान्वयन क्या है जो हमेशा सबसे संभव सटीक परिणाम देता है? यही है, अगर xऔर yफ्लोटिंग-पॉइंट नंबर हैं, तो फ़्लोटिंग-पॉइंट नंबर की गणना कैसे करें (x+y)/2? इस मामले में, गणना का मतलब स्वचालित रूप से >= min(x,y)और है <= max(x,y)। देखें डॉन हैच के जवाब जानकारी के लिए।

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


(+1) दिलचस्प सवाल, आश्चर्यजनक रूप से गैर-तुच्छ।
किरिल

1
अतीत में, फ़्लोटिंग पॉइंट वैल्यूज़ की गणना और मध्यवर्ती परिणामों के लिए उच्च परिशुद्धता रूप में की जाती थी। यदि एक + बी (64-बिट डबल्स) एक 80 बिट मध्यवर्ती परिणाम पैदा करता है और यह वही है जो 2 से विभाजित है, तो आपको अतिप्रवाह के बारे में चिंता करने की ज़रूरत नहीं है। परिशुद्धता का नुकसान कम स्पष्ट है।
JDługosz

इसका समाधान अपेक्षाकृत सरल लगता है ( मैंने एक उत्तर जोड़ा )। बात यह है कि मैं एक प्रोग्रामर हूं और कंप्यूटर विज्ञान विशेषज्ञ नहीं हूं, इसलिए मुझे क्या याद आ रहा है जो इस प्रश्न को इतना कठिन बना देता है?
IQAndreas

दो से गुणा और विभाजन की लागत के बारे में चिंता मत करो; आपका कंपाइलर आपके लिए उन्हें ऑप्टिमाइज़ करेगा।
फेडेरिको पोलोनी

जवाबों:


18

मुझे लगता है कि हिघम की सटीकता और न्यूमेरिकल एल्गोरिदम की स्थिरता से पता चलता है कि कोई भी इस प्रकार की समस्याओं का विश्लेषण कैसे कर सकता है। अध्याय 2 देखें, विशेष रूप से 2.8।

इस उत्तर में मैं कुछ ऐसी बात बताना चाहता हूं जो वास्तव में हिघम की पुस्तक में संबोधित नहीं की गई है (यह इस मामले के लिए बहुत व्यापक रूप से ज्ञात नहीं है)। यदि आप इन जैसे सरल संख्यात्मक एल्गोरिदम के गुणों को साबित करने में रुचि रखते हैं , तो आप आधुनिक SMT सॉल्वर ( Satisfiable Modulo Theories ) की शक्ति का उपयोग कर सकते हैं , जैसे कि z3 , जैसे Hbell में sbv जैसे पैकेज का उपयोग करना । यह पेंसिल और पेपर का उपयोग करने से कुछ आसान है।

मान लीजिए मैं दिया हूँ कि , और मुझे पता करना चाहते हैं तो जेड = ( x + y ) / 2 को संतुष्ट करता है एक्स जेड y । निम्नलिखित हास्केल कोड0xyz=(x+y)/2xzy

import Data.SBV

test1 :: (SFloat -> SFloat -> SFloat) -> Symbolic SBool
test1 fun =
  do [x, y] <- sFloats ["x", "y"]
     constrain $ bnot (isInfiniteFP x) &&& bnot (isInfiniteFP y)
     constrain $ 0 .<= x &&& x .<= y
     let z = fun x y
     return $ x .<= z &&& z .<= y

test2 :: (SFloat -> SFloat -> SFloat) -> Symbolic SBool
test2 fun =
  do [x, y] <- sFloats ["x", "y"]
     constrain $ bnot (isInfiniteFP x) &&& bnot (isInfiniteFP y)
     constrain $ x .<= y
     let z = fun x y
     return $ x .<= z &&& z .<= y

मुझे यह स्वचालित रूप से करने देगा । यहाँ test1 funहै प्रस्ताव है कि सभी परिमित तैरता के लिए एक्स , वाई के साथ 0 एक्स yxfun(x,y)yx,y0xy

λ> prove $ test1 (\x y -> (x + y) / 2)
Falsifiable. Counter-example:
  x = 2.3089316e36 :: Float
  y = 3.379786e38 :: Float

यह बह गया। मान लीजिए मैं अब आपका दूसरा सूत्र लेता हूं: z=x/2+y/2

λ> prove $ test1 (\x y -> x/2 + y/2)
Falsifiable. Counter-example:
  x = 2.3509886e-38 :: Float
  y = 2.3509886e-38 :: Float

काम नहीं करता है (क्रमिक अधःप्रवाह की वजह से: , जो सभी गणित किया जा रहा है आधार -2 unintuitive कारण हो सकता है)।(x/2)×2x

अब आज़माएँ :z=x+(yx)/2

λ> prove $ test1 (\x y -> x + (y-x)/2)
Q.E.D.

काम करता है! यह Q.E.D.एक प्रमाण है कि test1संपत्ति सभी फ्लोट के लिए रखती है जैसा कि ऊपर परिभाषित किया गया है।

xy0xy

λ> prove $ test2 (\x y -> x + (y-x)/2)
Falsifiable. Counter-example:
  x = -3.1300826e34 :: Float
  y = 3.402721e38 :: Float

yxz=x+(y/2x/2)

λ> prove $ test2 (\x y -> x + (y/2 - x/2))
Q.E.D.

x+(y/2x/2)

(x+y)/2

xx+(y/2x/2)ySFloatSDouble

-ffast-math(x+y)/2

पीपीपीएस मैं केवल साधारण बीजीय अभिव्यक्तियों को बिना किसी शर्त के देख रहा था। डॉन हैच का फार्मूला सख्ती से बेहतर है।


2
रुको; क्या आपने दावा किया है कि यदि x <= y (चाहे x> = 0 है या नहीं) तो x + (y / 2-x / 2) इसे करने का एक अच्छा तरीका है? मुझे लगता है कि यह सही नहीं हो सकता है, क्योंकि यह निम्नलिखित मामले में गलत उत्तर देता है जब उत्तर बिल्कुल प्रतिनिधित्व योग्य होता है: x = -1, y = 1 + 2 ^ -52 (1 से अधिक सबसे छोटा प्रतिनिधित्व योग्य संख्या), जिस स्थिति में उत्तर 2 ^ -53 है। अजगर में पुष्टि: >>> x = -1.; y = 1.+2.**-52; print `2**-53`, `(x+y)/2.`, `x+(y/2.-x/2.)`
डॉन हैच

2
@DonHatch मैंने "मजबूती" के बारे में सवाल का जवाब देने का लक्ष्य रखा: यह सुनिश्चित करना कि असमानताएं x(x+y)/2yx,y(x+y)/2(x+y)/2

8

सबसे पहले, यह देखें कि यदि आपके पास एक ऐसा तरीका है जो सभी मामलों में सबसे सटीक उत्तर देता है, तो यह आपकी आवश्यक स्थिति को पूरा करेगा। (नोट मैं कहता हूँ कि एक के बजाय सबसे सटीक उत्तर सबसे सटीक उत्तर के बाद से वहाँ दो विजेताओं हो सकता है।) प्रूफ: हैं, तो विपरीत करने के लिए, आप एक सटीक के रूप में संभव जवाब यह है कि करता है नहीं आवश्यक शर्त पूरी कि या तो इसका मतलब है (किस मामले में एक बेहतर जवाब है, एक विरोधाभास), या (किस मामले में एक बेहतर जवाब है, एक विरोधाभास)।answer<min(x,y)<=max(x,y)min(x,y)min(x,y)<=max(x,y)<answermax(x,y)

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

if max(abs(x),abs(y)) >= 1.:
    return x/2. + y/2.
else:
    return (x+y)/2.

मेरा तर्क है कि यह सबसे सटीक उत्तर देता है कुछ हद तक थकाऊ विश्लेषण है। यहाँ जाता हैं:

  • मामला max(abs(x),abs(y)) >= 1.:

    • सबकेस न तो x और न ही y को असमान किया जाता है: इस मामले में गणना किए गए उत्तर x/2.+y/2.एक ही मन्तीस में हेरफेर करते हैं और इसलिए (x+y)/2यदि हम अतिप्रवाह को रोकने के लिए विस्तारित प्रतिपादक मान लेते हैं, तो गणना के रूप में सटीक उत्तर देगा। यह उत्तर राउंडिंग मोड पर निर्भर हो सकता है लेकिन किसी भी मामले में IEEE754 द्वारा x+yइसकी गारंटी दी जाती है कि यह एक सर्वोत्तम संभव उत्तर हो (इस तथ्य से कि गणना गणितीय x + y के लिए एक सर्वश्रेष्ठ सन्निकटन होने की गारंटी है, और 2 द्वारा विभाजन इस में सटीक है मामला)।
    • सबकेस x को असामान्य (और इसलिए abs(y)>=1):

      answer = x/2. + y/2. = y/2. since abs(x/2.) is so tiny compared to abs(y/2.) = the exact mathematical value of y/2 = a best possible answer.

    • सबकेस वाई को अपभ्रंश किया जाता है (और इसलिए abs(x)>=1): अनुरूप।

  • मामला max(abs(x),abs(y)) < 1.:
    • उपखंड गणना x+yया तो गैर-अपभ्रंश या अपभ्रंश है और-"यहां तक ​​कि": यद्यपि गणना x+yसटीक नहीं हो सकती है, यह IEEE754 द्वारा गणितीय x + y के लिए एक सर्वोत्तम संभव सन्निकटन होने की गारंटी है। इस मामले में अभिव्यक्ति में 2 से बाद का विभाजन (x+y)/2.सटीक है, इसलिए गणना किए गए उत्तर (x+y)/2.गणितीय (x + y) / 2 के लिए सबसे अच्छा संभव सन्निकटन है।
    • उपखंड गणना x+yको असमान और "विषम" किया जाता है: इस स्थिति में x, y को भी समान रूप से निरूपित किया जाना चाहिए और- "विषम", जिसका अर्थ है कि x के दूसरे, y को विपरीत चिन्ह के साथ निरूपित किया गया है, और इसलिए गणना की गई x+yहै बिल्कुल गणितीय x + y, और इसलिए गणना (x+y)/2.की गई IEEE754 द्वारा गणितीय (x + y) / 2 के लिए एक सर्वोत्तम संभव सन्निकटन होने की गारंटी है।

मुझे एहसास हो रहा है जब मैंने कहा कि "असामान्य रूप से" मेरा वास्तव में कुछ और मतलब था - अर्थात्, संख्याएं जो एक दूसरे के करीब हैं जितनी संख्याएं मिलती हैं, अर्थात संख्याओं की सीमा जो लगभग दो गुना बड़ी है जितना कि असामान्य संख्याओं की सीमा, यानी पहले 8 टिक या तो आरेख में en.wikipedia.org/wiki/Denormal_number पर । मुद्दा यह है कि, इनमें से "विषम" एक ही संख्या है जिसके लिए उन्हें दो से विभाजित करना सटीक नहीं है। मुझे यह स्पष्ट करने के लिए उत्तर के इस भाग को फिर से उद्धृत करना होगा।
डॉन हैच

fl(op(x,y))=op(x,y)(1+δ)|δ|ux/2+y/2(x+y)/2हमेशा सही ढंग से गोल, अनुपस्थित ओवर- / अंडरफ्लो होते हैं, जो कुछ बचा है, वह ओवर- / अंडरफ्लो में कुछ भी नहीं दिखाना है, जो आसान है।
किरिल

@Kirill मैं थोड़ा खो गया हूँ ... तुम कहाँ से आए हो? इसके अलावा, मुझे नहीं लगता कि यह सच है कि "2 से विभाज्य गैर-असमान संख्याओं के लिए सटीक हैं" ... यह वही चीज है जिसे मैंने खत्म कर दिया है, और यह सही होने की कोशिश करने के लिए थोड़ा अजीब लग रहा है। सटीक कथन कुछ और है जैसे "x / 2 बिल्कुल सटीक है जब तक कि abs (x) कम से कम दो बार सबसे बड़ी सबऑनॉर्मल संख्या" ... argh, awkward!
डॉन हैच

3

IEEE-754 बाइनरी फ़्लोटिंग-पॉइंट प्रारूपों के लिए, binary64एस (बोल्ड सटीक) गणना द्वारा, एस बोल्डो ने औपचारिक रूप से साबित कर दिया कि नीचे दिखाया गया सरल एल्गोरिथ्म सही ढंग से गोल औसत देता है।

सिल्वी बोल्डो, "फ़्लोटिंग-पॉइंट औसत की गणना करने वाले कार्यक्रमों का औपचारिक सत्यापन।" में पर औपचारिक इंजीनियरिंग के तरीके अंतर्राष्ट्रीय सम्मेलन , पीपी। 17-32। स्प्रिंगर, चम, 2015 ( ऑनलाइन मसौदा )

(x+y)/2x/2+y/2binary64C[2967,2970]C एक विशेष उपयोग के मामले के लिए सबसे अच्छा प्रदर्शन प्रदान करने के लिए।

यह निम्नलिखित अनुकरणीय ISO-C99कोड देता है:

double average (double x, double y) 
{
    const double C = 1; /* 0x1p-967 <= C <= 0x1p970 */
    return (C <= fabs (x)) ? (x / 2 + y / 2) : ((x + y) / 2);
}

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

सिल्वी बोल्डो, फ्लोरियन फैसोल, और विन्सेन्ट टूरनेउर, "डेसीमल फ्लोटिंग-पॉइंट नंबर्स के सही औसत की गणना करने के लिए एक औपचारिक रूप से साबित एल्गोरिदम।" में कंप्यूटर अंकगणित (ARITH 25) पर 25 वीं आईईईई संगोष्ठी जून 2018, पृ। 69-75। ( ऑनलाइन मसौदा )


2

यद्यपि यह सुपर-कुशल प्रदर्शन-वार नहीं हो सकता है, (1) यह सुनिश्चित करने का एक बहुत ही सरल तरीका है कि संख्याओं में से कोई भी xया तो अधिक yनहीं है या (कोई ओवरफ्लो) नहीं है और (2) फ्लोटिंग बिंदु को "सटीक" के रूप में रखें संभव (और (3) , एक अतिरिक्त बोनस के रूप में, भले ही घटाव का उपयोग किया जा रहा हो, कोई भी मान कभी भी ऋणात्मक संख्याओं के रूप में संग्रहीत नहीं किया जाएगा।

float difference = max(x, y) - min(x, y);
return min(x, y) + (difference / 2.0);

वास्तव में, यदि आप वास्तव में सटीकता के लिए जाना चाहते हैं , तो आपको मौके पर विभाजन करने की आवश्यकता नहीं है; बस के मूल्यों को लौटाएं min(x, y)और differenceजिसका उपयोग आप तार्किक रूप से सरल बनाने या बाद में हेरफेर करने के लिए कर सकते हैं।


मैं अब यह पता लगाने की कोशिश कर रहा हूं कि दो से अधिक वस्तुओं के साथ यह एक ही उत्तर का काम कैसे किया जाए , जबकि सभी चर सबसे बड़ी संख्या से कम रहते हैं, और सटीकता को संरक्षित करने के लिए केवल एक विभाजन ऑपरेशन का उपयोग करते हैं।
IQAndreas

@becko हाँ, आप कम से कम दो बार विभाजन कर रहे होंगे। इसके अलावा, आपने जो उदाहरण दिया है, उसका उत्तर गलत होगा। के माध्य की कल्पना करें 2,4,9, यह माध्य के समान नहीं है 3,9
IQAndreas

आप सही हैं, मेरी पुनरावृत्ति गलत थी। मुझे यकीन नहीं है कि सटीक तरीके से खोए बिना, इसे अभी कैसे ठीक किया जाए।
बेको

क्या आप साबित कर सकते हैं कि यह सबसे सटीक संभव परिणाम देता है? यही है, अगर xऔर yफ्लोटिंग-पॉइंट हैं, तो आपकी गणना एक फ्लोटिंग-पॉइंट को निकटतम बनाती है (x+y)/2?
becko

1
क्या यह अतिप्रवाह तब नहीं होगा, जब x, y सबसे कम और सबसे अधिक व्यक्त संख्याएँ हों?
डॉन हैच

1

उच्च प्रसार में कनवर्ट करें, वहां मान जोड़ें और वापस कनवर्ट करें।

उच्च प्रसार में कोई अतिप्रवाह नहीं होना चाहिए और यदि दोनों वैध फ्लोटिंग पॉइंट रेंज में हैं, तो गणना की गई संख्या भी अंदर होनी चाहिए।

और यह उन दोनों के बीच में होना चाहिए, सबसे बड़ी संख्या केवल बड़ी संख्या का आधा है यदि प्रीसिशन पर्याप्त नहीं है।


यह ब्रूट फोर्स एप्रोच है। यह शायद काम करता है, लेकिन मैं एक विश्लेषण की तलाश में था जिसे मध्यवर्ती उच्च परिशुद्धता की आवश्यकता नहीं थी। इसके अलावा, क्या आप अनुमान लगा सकते हैं कि मध्यवर्ती उच्च परिशुद्धता की कितनी आवश्यकता है? किसी भी स्थिति में, इस उत्तर (+1) को न हटाएं, मैं इसे उत्तर के रूप में स्वीकार नहीं करूंगा।
becko

1

सैद्धांतिक रूप x/2से, मंटिसा से 1 घटाकर गणना की जा सकती है।

हालांकि, वास्तव में इस तरह से बिटवाइज़ ऑपरेशंस को लागू करना आवश्यक नहीं है, खासकर यदि आप अपने फ्लोटिंग पॉइंट नंबरों के प्रारूप को नहीं जानते हैं।

यदि आप ऐसा कर सकते हैं, तो पूरे ऑपरेशन को 3 जोड़ / घटाया जाता है, जो एक महत्वपूर्ण सुधार होना चाहिए।


0

मैं @Roland हीथ के रूप में एक ही पंक्ति के साथ सोच रहा था, लेकिन अभी तक टिप्पणी नहीं कर सकता, यहाँ मेरा है:

x/2प्रतिपादक से 1 घटाकर गणना की जा सकती है (मंटिसा नहीं, मंटिसा से 1 घटाना 2^(value_of_exponent-length_of_mantissa)समग्र मूल्य से घटाना है)।

सामान्य मामले के प्रतिबंध के बिना, मान लेते हैं x < y। (यदि x > y, चर को पुनः वितरित करें। यदि x = y, (x+y) / 2तुच्छ है।)

  • रूपांतरण (x+y) / 2मेंx/2 + y/2 (प्रतिपादक से एक के बाद) दो पूर्णांक subtractions द्वारा, किया जा सकता है जो
    • हालाँकि आपके प्रतिनिधित्व के आधार पर प्रतिपादक पर एक कम बाध्यता है। यदि आपका घातांक 1 घटने से पहले ही न्यूनतम है, तो इस विधि को विशेष मामले से निपटने की आवश्यकता होगी। एक न्यूनतम घातांक अभाज्य से छोटा xबना देगा x/2(यह मानते हुए कि मन्तिसा एक निहित प्रमुख 1 से दर्शाया गया है)।
    • 1 के घातांक से घटाकर 1 के स्थान पर मंटिसा को दाईं ओर xशिफ्ट करें x(और निहित 1 को जोड़ दें, यदि कोई हो)।
    • Y के घातांक से 1 घटाएं, यदि यह न्यूनतम नहीं है। यदि यह न्यूनतम है (y, mantissa के कारण x से बड़ा है), तो mantissa को दाईं ओर एक-एक करके स्थानांतरित करें (जोड़ 1, यदि कोई हो तो जोड़कर देखें)।
    • xके घातांक के अनुसार दाईं ओर के नए मंटिसा को शिफ्ट करेंy
    • मंटिसा पर पूर्णांक जोड़कर प्रदर्शन करें, जब तक कि मंटिसा को xपूरी तरह से स्थानांतरित नहीं किया गया हो। यदि दोनों घातांक न्यूनतम थे, तो प्रमुख अतिप्रवाह होंगे, जो ठीक है, क्योंकि यह अतिप्रवाह एक अंतर्निहित प्रमुख बनने वाला है।
  • और एक अस्थायी बिंदु जोड़।
    • यहाँ किसी विशेष मामले के बारे में नहीं सोच सकते; गोलाई को छोड़कर, जो ऊपर वर्णित शिफ्टिंग पर भी लागू होता है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.