मापांक विभाजन (%) केवल पूर्णांक के साथ क्यों काम करता है?


79

मैं हाल ही में एक ऐसे मुद्दे पर भाग गया जिसे आसानी से मापांक विभाजन का उपयोग करके हल किया जा सकता था, लेकिन इनपुट एक फ्लोट था:

एक आवधिक फ़ंक्शन (जैसे sin) और एक कंप्यूटर फ़ंक्शन को देखते हुए जो केवल अवधि सीमा (जैसे [-π, make]) के भीतर गणना कर सकते हैं, एक फ़ंक्शन बनाते हैं जो किसी भी इनपुट को संभाल सकता है।

"स्पष्ट" समाधान कुछ इस प्रकार है:

#include <cmath>

float sin(float x){
    return limited_sin((x + M_PI) % (2 *M_PI) - M_PI);
}

यह काम क्यों नहीं करता है? मुझे यह त्रुटि मिली:

error: invalid operands of types double and double to binary operator %

दिलचस्प है, यह पायथन में काम करता है:

def sin(x):
    return limited_sin((x + math.pi) % (2 * math.pi) - math.pi)

20
, 3.14 के बराबर नहीं है, और वास्तव में किसी भी फ्लोटिंग पॉइंट प्रकार के रूप में इसका प्रतिनिधित्व करने योग्य नहीं है। वास्तव में sin(x)बड़े मूल्यों के लिए कम्प्यूटिंग के लिए xएक बहुत ही कठिन ट्रान्सेंडैंटल तर्क कटौती प्रक्रिया की आवश्यकता होती है जो किसी भी परिमित सन्निकटन के साथ नहीं मिल सकती है।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

3
यह लगभग निश्चित रूप से एक होमवर्क असाइनमेंट है, इसलिए फ्लोटिंग पॉइंट त्रुटियां या तो असाइनमेंट के दायरे से बाहर हैं, या इसका मतलब अधिक कठोर संख्यात्मक विश्लेषण की चर्चा करना है। किसी भी तरह से, fmodसंभावना है कि प्रशिक्षक क्या देख रहा है।
डेनिस ज़िकफोज़

2
यह होमवर्क नहीं है, यह सिर्फ कुछ है कि आया एक और तो सवाल (पढ़ते समय है stackoverflow.com/questions/6091837/... )
ब्रेंडन लौंग

2
ठीक है, मुझे अपने बयान में अधिक सटीक होना चाहिए था। मेरा कहना था कि यदि तर्क निर्बाध रूप से बड़ा हो सकता है (न कि केवल डबल सटीक प्रतिपादक आकार), तो पीआई का कोई परिमित अनुमान पर्याप्त नहीं होगा। डबल के लिए, हाँ, पाई का एक बहुत लंबा सन्निकटन पर्याप्त होगा।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

1
@aschepler: मुझे नहीं लगता कि आप इस मुद्दे को समझ पाए हैं।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

जवाबों:


76

क्योंकि "शेष" की सामान्य गणितीय धारणा केवल पूर्णांक विभाजन पर लागू होती है। यानी विभाजन जो पूर्णांक भागफल उत्पन्न करने के लिए आवश्यक है।

वास्तविक संख्याओं के लिए "शेष" की अवधारणा को विस्तारित करने के लिए आपको एक नए प्रकार के "हाइब्रिड" ऑपरेशन को पेश करना होगा जो वास्तविक ऑपरेंड के लिए पूर्णांक भागफल उत्पन्न करेगा । कोर सी भाषा इस तरह के ऑपरेशन का समर्थन नहीं करती है, लेकिन यह एक मानक पुस्तकालय फ़ंक्शन के साथ-साथ C99 में कार्य करती है। (ध्यान दें कि ये फ़ंक्शन समान नहीं हैं और कुछ ख़ासियत हैं। विशेष रूप से, वे पूर्णांक विभाजन के नियमों का पालन नहीं करते हैं।)fmodremainder


7
98 मानक में% की परिभाषा से: ", (a / b) * b + a% b एक के बराबर है।" फ्लोटिंग पॉइंट प्रकारों के लिए, (a/b)*bपहले से ही बराबर है a[जैसे कि फ़्लोटिंग पॉइंट प्रकारों के लिए ऐसा स्टेटमेंट बनाया जा सकता है], इसलिए a%bयह विशेष रूप से उपयोगी नहीं होगा।
डेनिस ज़िकफ़ोज़

1
@ डेनिस: वास्तव में, बीजगणितीय रूप से, एक क्षेत्र में शेष हमेशा 0 होता है। %फ्लोटिंग पॉइंट के लिए ऑपरेटर की सबसे उपयुक्त परिभाषा , मुझे लगता है a-(a/b)*b, जो या तो 0 या बहुत छोटा मूल्य होगा।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

7
@ डेनिस: आप इस फॉर्मूले को आसानी से तय कर सकते हैं कि "मंजिल (a / b) * b + a% b = a"। ध्यान दें कि पूर्णांकों के लिए, फर्श (ए / बी) = ए / बी।
VOG

सी-स्टाइल पूर्णांक विभाजन ट्रंक का उपयोग करता है, न कि मंजिल का, लेकिन बिंदु बना रहता है।
dan04

18
-1 रे "" शेष "की सामान्य गणितीय धारणा केवल पूर्णांक विभाजन पर लागू होती है", मोडुलो अंकगणितीय की गणितीय धारणा फ्लोटिंग पॉइंट मानों के लिए भी काम करती है, और यह पहले मुद्दों में से एक है जो डोनाल्ड नुथ अपने क्लासिक में चर्चा करता है । कंप्यूटर प्रोग्रामिंग (वॉल्यूम I) की कला । यानी यह एक बार बुनियादी ज्ञान था। आज, छात्र आईएमएचओ के लिए जो शिक्षा देते हैं, उसे प्राप्त नहीं करते हैं।
चीयर्स एंड हीथ। - अल्फ

52

आप fmod () की तलाश में हैं

मैं अधिक विशेष रूप से आपके प्रश्न का उत्तर देने का अनुमान लगाता हूं, पुरानी भाषाओं में %ऑपरेटर को पूर्णांक मॉड्यूलर विभाजन के रूप में परिभाषित किया गया था और नई भाषाओं में उन्होंने ऑपरेटर की परिभाषा का विस्तार करने का निर्णय लिया था।

संपादित करें: यदि मुझे एक अनुमान लगाना था कि क्यों, मैं यह कहूंगा कि मॉड्यूलर अंकगणित का विचार संख्या सिद्धांत में उत्पन्न होता है और विशेष रूप से पूर्णांक के साथ संबंधित है।


9
"पुरानी भाषाएं" - APL 1960 के दशक की है, और इसका मॉडुलो ऑपरेटर है। "" दोनों पूर्णांक और फ्लोटिंग पॉइंट डेटा (स्केलर, वेक्टर, मैट्रिक्स, टेंसर, ...) के साथ काम करता है। कोई अच्छा कारण नहीं है कि C का "%" मोड्यूलो ऑपरेटर फ्लोमिंग पॉइंट नंबरों के साथ उपयोग किए जाने पर fmod के समान कार्य नहीं कर सकता है।
rcgldr

@rcgldr डिज़ाइन लक्ष्यों को फ़्लोटिंग पॉइंट मोडुलो की आवश्यकता नहीं थी। सी को यूनिक्स को संकलित करने और ओएस के लिए आवश्यक विधानसभा भाषा की मात्रा को सीमित करने के लिए लागू किया गया था। "सी एक अनिवार्य प्रक्रियात्मक भाषा है। इसे अपेक्षाकृत सरल संकलक का उपयोग करके संकलित किया जाना था, ताकि स्मृति को निम्न-स्तरीय पहुंच प्रदान की जा सके, मशीन निर्माण के निर्देशों को कुशलतापूर्वक मैप करने के लिए भाषा निर्माण प्रदान करने के लिए, और न्यूनतम रन-टाइम समर्थन की आवश्यकता होती है।" en.wikipedia.org/wiki/C_(programming_language)
हार्पर

1
@harper - चूँकि C में फ़्लोटिंग पॉइंट अंकगणित शामिल है जैसे कि ऐड, घटाना, गुणा, और डिवाइड करना, उसी सिंटैक्स का उपयोग करना जो यह पूर्णांकों के लिए करता है, मैं यह नहीं देखता कि इसमें समान सिंटैक्स (%) का उपयोग करके मॉडुलो को भी शामिल क्यों नहीं किया जा सकता है । इसे शामिल करने या न करने का विकल्प मनमाना लगता है।
rcgldr

16

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


1
+1 पहला वाजिब जवाब होने के कारण मैं देख रहा हूं जैसे मैं सूची को पढ़ रहा हूं। दरअसल, अब उन सभी को पढ़ना, यह एकमात्र उचित जवाब है।
चीयर्स एंड हीथ। - अल्फ

मुझ से भी एक बेल्ड। मैं 6809 और Z80 एम्बेडेड सिस्टम के लिए सी में लिखता था। कोई भी तरीका मैं सी रनटाइम लाइब्रेरी को शामिल करने के लिए जगह नहीं दे सकता था। यहां तक ​​कि मुझे अपना स्टार्टअप कोड भी लिखना पड़ा। फ़्लोटिंग पॉइंट एक लक्जरी था जिसे मैं बर्दाश्त नहीं कर सकता था :)
रिचर्ड होजेस

12

%C और C ++ में modulo ऑपरेटर को दो पूर्णांकों के लिए परिभाषित किया गया है, हालांकि, fmod()युगल के साथ उपयोग के लिए एक फ़ंक्शन उपलब्ध है।


4
यह ओपी के सवाल का जवाब है, लेकिन ओपी जो करने की कोशिश कर रहा है उसमें मूलभूत समस्या को नजरअंदाज करता है: sin(fmod(x,3.14))या यहां तक sin(fmod(x,M_PI))कि अन्य sin(x)मूल्यों के बराबर नहीं है x। वास्तव में मान 2.0 से भिन्न हो सकते हैं।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

2
@ आर ..: सही है, लेकिन यह एक अलग सवाल है और मुझे पूरी तरह से यकीन नहीं है कि एक स्वीकृत जवाब है, हालांकि इस विषय पर
मार्क इलियट

@ आर - मैंने इसे सही ढंग से करने के लिए समीकरण तय किया। वास्तविक समीकरण बिंदु नहीं था (यह पता लगाने के लिए कि मेरे पास इसका परीक्षण करने के लिए एक बार यह पता लगाना काफी आसान था)।
ब्रेंडन लांग

क्या %शेष संचालक नहीं है और मोडुलो संचालक नहीं है?
chux -

7

बाधाओं मानकों में हैं:

C11 (ISO / IEC 9899: 201x) .56.5.5 मल्टीप्लिक्टिव ऑपरेटर्स

प्रत्येक ऑपरेंड में अंकगणित प्रकार होगा। % ऑपरेटर के ऑपरेटर के पूर्णांक प्रकार होंगे।

C ++ 11 (ISO / IEC 14882: 2011) Mult5.6 मल्टीप्लिकेटेटिव ऑपरेटर

* और / या के अंकगणित या गणना प्रकार होंगे; % के ऑपरेंड में अभिन्न या गणना प्रकार होगा। सामान्य अंकगणितीय रूपांतरण ऑपरेंड पर किए जाते हैं और परिणाम के प्रकार को निर्धारित करते हैं।

समाधान उपयोग करने के लिए है fmodजो वास्तव में है, क्यों की ऑपरेंड %पहली जगह में पूर्णांक प्रकार तक सीमित हैं, के अनुसार C99 दलील §6.5.5 Multiplicative ऑपरेटरों :

C89 समिति ने फ्लोटिंग प्रकारों पर काम करने के लिए% ऑपरेटर का विस्तार करने से इनकार कर दिया क्योंकि इस तरह का उपयोग fmod द्वारा प्रदान की गई सुविधा की नकल करेगा



2

% ऑपरेटर आपको एक नंबर का एक REMAINDER (मापांक का दूसरा नाम) देता है। C / C ++ के लिए, यह केवल पूर्णांक परिचालनों के लिए परिभाषित किया गया है। पायथन थोड़ा व्यापक है और आपको शेष के लिए एक फ्लोटिंग पॉइंट नंबर प्राप्त करने की अनुमति देता है कि कितनी बार संख्या को इसमें विभाजित किया जा सकता है:

>>> 4 % math.pi
0.85840734641020688
>>> 4 - math.pi
0.85840734641020688
>>> 

2
अवशेष ' मॉडुलस का दूसरा नाम' नहीं है !! देखें: stackoverflow.com/questions/13683563/… या एक गणित-पीओवी से: math.stackexchange.com/questions/801962/… सीधे शब्दों में कहें : modulo और शेष केवल सकारात्मक संख्याओं के लिए समान हैं और एक अन्य उदाहरण यह है कि शेष बचे ' t आपको कम्पास (प्रति-घड़ी) के चारों ओर जाने देता है। कृपया सही करें कि जैसा कि मैं :P
नीचा दिखाने के लिए हूं

2

%ऑपरेटर C ++ काम नहीं करता है, जब आप दो नंबर दोनों प्रकार के होते हैं जो के शेष खोजने की कोशिश कर रहे हैं Floatया Double

इसलिए आप उपयोग कर की कोशिश कर सकते fmodसे समारोह math.h/ cmath.hया आप कोड की इन पंक्तियों का उपयोग करें कि हेडर फाइल का उपयोग कर से बचने के लिए कर सकते हैं:

float sin(float x) {
 float temp;
 temp = (x + M_PI) / ((2 *M_PI) - M_PI);
 return limited_sin((x + M_PI) - ((2 *M_PI) - M_PI) * temp ));

}


1

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

अस्थायी बिंदु मापांक ऑपरेटर को निम्नानुसार परिभाषित किया गया है:

m = num - iquot*den ; where iquot = int( num/den )

जैसा कि संकेत दिया गया है, फ़्लोटिंग पॉइंट नंबरों पर% ऑपरेटर का नो-ऑप मानक से संबंधित प्रतीत होता है। CRTL 'fmod' प्रदान करता है, और आमतौर पर 'शेष' के रूप में, fp संख्याओं पर% करने के लिए। इन दोनों के बीच अंतर यह है कि वे मध्यवर्ती 'आईक्वाट' को कैसे गोल करते हैं।

'शेष' गोल-से-निकटतम का उपयोग करता है, और 'fmod' सरल ट्रंकट का उपयोग करता है।

यदि आप अपनी स्वयं की C ++ संख्यात्मक कक्षाएं लिखते हैं, तो कुछ भी आपको ओवरलोड ऑपरेटर% सहित, नो-ऑप विरासत को संशोधित करने से रोकता है।

सादर

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.