आपका कोड पूरी तरह से ठीक है
आप बिल्कुल सही हैं और आपका शिक्षक गलत है। उस अतिरिक्त जटिलता को जोड़ने के लिए बिल्कुल कोई कारण नहीं है, क्योंकि यह परिणाम को बिल्कुल प्रभावित नहीं करता है। यह भी एक बग का परिचय देता है। (निचे देखो)
पहला, यदि अलग-अलग चेक n
शून्य है तो स्पष्ट रूप से पूरी तरह से अनावश्यक है और यह महसूस करना बहुत आसान है। ईमानदार होने के लिए, मैं वास्तव में आपके शिक्षकों की योग्यता पर सवाल उठाता हूं अगर उसे इस बारे में आपत्ति है। लेकिन मुझे लगता है कि हर कोई समय-समय पर एक मस्तिष्क गोज़ हो सकता है। हालाँकि, मुझे लगता है कि while(n)
इसे बदल दिया जाना चाहिए while(n != 0)
क्योंकि यह एक अतिरिक्त लाइन की लागत के बिना थोड़ा अतिरिक्त स्पष्टता जोड़ता है। हालांकि यह मामूली बात है।
दूसरा वाला थोड़ा अधिक समझ में आता है, लेकिन वह अभी भी गलत है।
यह C11 मानक 6.5.5.p6 कहता है:
यदि भागफल a / b प्रतिनिधित्व योग्य है, तो अभिव्यक्ति (a / b) * b + a% b बराबर होगी a; अन्यथा, a / b और% b दोनों का व्यवहार अपरिभाषित है।
फुटनोट कहता है:
इसे अक्सर "शून्य की ओर झुकाव" कहा जाता है।
शून्य साधन की ओर ट्रंकेशन कि के लिए निरपेक्ष मूल्य a/b
है के लिए निरपेक्ष मूल्य के बराबर (-a)/b
सभी के लिए a
और b
जो बारी साधन में अपने कोड बिल्कुल ठीक है कि,।
मोदुलो आसान गणित है, लेकिन प्रतिवाद हो सकता है
हालाँकि, आपके शिक्षक के पास एक बिंदु है कि आपको सावधान रहना चाहिए, क्योंकि इस तथ्य को कि आप परिणाम को चुकता कर रहे हैं, वास्तव में यहाँ महत्वपूर्ण है। a%b
उपरोक्त परिभाषा के अनुसार गणना करना आसान गणित है, लेकिन यह आपके अंतर्ज्ञान के खिलाफ जा सकता है। गुणन और विभाजन के लिए, परिणाम सकारात्मक है यदि ऑपरेंड्स के बराबर चिह्न हैं। लेकिन जब मोडुलो की बात आती है, तो परिणाम में पहले ऑपरेंड के समान संकेत होते हैं । दूसरा ऑपरेंड संकेत को प्रभावित नहीं करता है। उदाहरण के लिए, 7%3==1
लेकिन (-7)%(-3)==(-1)
।
यहाँ एक स्निपेट प्रदर्शित किया गया है:
$ cat > main.c
#include <stdio.h>
void f(int a, int b)
{
printf("a: %2d b: %2d a/b: %2d a\%b: %2d (a%b)^2: %2d (a/b)*b+a%b==a: %5s\n",
a, b ,a/b, a%b, (a%b)*(a%b), (a/b)*b+a%b == a ? "true" : "false");
}
int main(void)
{
int a=7, b=3;
f(a,b);
f(-a,b);
f(a,-b);
f(-a,-b);
}
$ gcc main.c -Wall -Wextra -pedantic -std=c99
$ ./a.out
a: 7 b: 3 a/b: 2 a%b: 1 (a%b)^2: 1 (a/b)*b+a%b==a: true
a: -7 b: 3 a/b: -2 a%b: -1 (a%b)^2: 1 (a/b)*b+a%b==a: true
a: 7 b: -3 a/b: -2 a%b: 1 (a%b)^2: 1 (a/b)*b+a%b==a: true
a: -7 b: -3 a/b: 2 a%b: -1 (a%b)^2: 1 (a/b)*b+a%b==a: true
इसलिए, विडंबना यह है कि आपके शिक्षक ने गलत होने से अपनी बात साबित की।
आपके शिक्षक का कोड त्रुटिपूर्ण है
हाँ, यह वास्तव में है। यदि इनपुट है INT_MIN
और आर्किटेक्चर दो का पूरक है और बिट पैटर्न जहां साइन बिट 1 है और सभी वैल्यू बिट्स 0 हैं, ट्रैप वैल्यू नहीं है (ट्रैप वैल्यू के बिना दो के पूरक का उपयोग करना बहुत सामान्य है) तो आपके शिक्षक का कोड अपरिभाषित व्यवहार करेगा लाइन पर n = n * (-1)
। आपका कोड है - अगर कभी इतना थोड़ा - उससे बेहतर । और कोड को अनावश्यक जटिल बनाकर और बिल्कुल शून्य मान प्राप्त करके एक छोटे से बग को शुरू करने पर विचार करते हुए, मैं कहूंगा कि आपका कोड बेहतर है।
दूसरे शब्दों में, संकलन में जहां INT_MIN = -32768 (भले ही परिणामी फ़ंक्शन एक इनपुट प्राप्त नहीं कर सकता है <-32768 या> 32767), -32768 का वैध इनपुट अपरिभाषित व्यवहार का कारण बनता है, क्योंकि - (- 32768i16) का परिणाम 16-बिट पूर्णांक के रूप में व्यक्त नहीं किया जा सकता है। (वास्तव में, -32768 शायद गलत परिणाम का कारण नहीं बनेगा, क्योंकि - (- 32768i16) आमतौर पर -32768i16 का मूल्यांकन करता है, और आपका प्रोग्राम नकारात्मक संख्याओं को सही ढंग से संभालता है।) (SHRT_MIN संकलक के आधार पर -3288 या -32767 हो सकता है।)
लेकिन आपके शिक्षक ने स्पष्ट रूप से कहा कि n
यह सीमा [-10 ^ 7 में हो सकती है; 10 ^ 7]। एक 16-बिट पूर्णांक बहुत छोटा है; आपको 32-बिट पूर्णांक [कम से कम] का उपयोग करना होगा। का उपयोग int
कर अपने कोड को सुरक्षित करने के लिए लग सकता है, सिवाय इसके कि int
एक 32-बिट पूर्णांक आवश्यक नहीं है। यदि आप 16-बिट आर्किटेक्चर के लिए संकलन करते हैं, तो आपके दोनों कोड स्निपेट त्रुटिपूर्ण हैं। लेकिन आपका कोड अभी भी बहुत बेहतर है क्योंकि यह परिदृश्य INT_MIN
उसके संस्करण के साथ ऊपर उल्लिखित बग को फिर से प्रस्तुत करता है । इससे बचने के लिए, आप long
इसके बजाय लिख सकते हैं int
, जो कि आर्किटेक्चर पर 32-बिट पूर्णांक है। ए long
की गारंटी है कि रेंज में किसी भी मूल्य को धारण करने में सक्षम होने के लिए [-2147483647; 2147483647]। C11 स्टैंडर्ड 5.2.4.2.1 LONG_MIN
अक्सर होता है-2147483648
लेकिन अधिकतम (हाँ, अधिकतम, यह एक नकारात्मक संख्या है) के लिए अनुमत मूल्य LONG_MIN
है 2147483647
।
मैं आपके कोड में क्या बदलाव करूंगा?
आपका कोड ठीक है जैसा कि यह है, इसलिए ये वास्तव में शिकायत नहीं हैं। यह अधिक पसंद है अगर मैं वास्तव में, वास्तव में आपके कोड के बारे में कुछ भी कहने की आवश्यकता है, तो कुछ छोटी चीजें हैं जो इसे बस थोड़ा सा स्पष्ट कर सकती हैं।
- चरों का नाम थोड़ा बेहतर हो सकता है, लेकिन यह एक छोटा कार्य है जिसे समझना आसान है, इसलिए यह कोई बड़ी बात नहीं है।
- आप से हालत बदल सकता है
n
के लिए n!=0
। शब्दार्थ, यह 100% समतुल्य है, लेकिन यह इसे थोड़ा स्पष्ट करता है।
- जब तक यह केवल वहाँ उपयोग किया जाता है, तब तक लूप के अंदर
c
(जिसे मैंने नाम दिया था digit
) की घोषणा को स्थानांतरित करें ।
long
यह सुनिश्चित करने के लिए कि यह पूरे इनपुट सेट को संभाल सके तर्क प्रकार बदलें ।
int sum_of_digits_squared(long n)
{
long sum = 0;
while (n != 0) {
int digit = n % 10;
sum += (digit * digit);
n /= 10;
}
return sum;
}
वास्तव में, यह थोड़ा भ्रामक हो सकता है क्योंकि - जैसा कि ऊपर बताया गया है - चर digit
एक नकारात्मक मूल्य प्राप्त कर सकता है, लेकिन एक अंक अपने आप में कभी भी सकारात्मक या नकारात्मक नहीं होता है। इसके आस-पास कुछ तरीके हैं, लेकिन यह वास्तव में नाइटपैकिंग है, और मैं इस तरह के छोटे विवरणों की परवाह नहीं करूंगा। विशेष रूप से अंतिम अंक के लिए अलग कार्य इसे बहुत दूर ले जा रहा है। विडंबना यह है कि यह उन चीजों में से एक है जो आपके शिक्षक कोड वास्तव में हल करते हैं।
- चर को पूरी तरह
sum += (digit * digit)
से बदलें sum += ((n%10)*(n%10))
और छोड़ें digit
।
digit
नकारात्मक होने पर संकेत बदलें । लेकिन मैं दृढ़ता से कोड को और अधिक जटिल बनाने के खिलाफ सलाह दूंगा कि केवल एक चर नाम बनाने का मतलब है। यह एक बहुत मजबूत कोड गंध है।
- एक अलग फ़ंक्शन बनाएँ जो अंतिम अंक निकालता है।
int last_digit(long n) { int digit=n%10; if (digit>=0) return digit; else return -digit; }
यह उपयोगी है यदि आप उस फ़ंक्शन को कहीं और उपयोग करना चाहते हैं।
c
जैसा कि आप मूल रूप से करते हैं, वैसे ही इसे नाम दें । वह परिवर्तनशील नाम कोई उपयोगी जानकारी नहीं देता है, लेकिन दूसरी ओर, यह भ्रामक भी नहीं है।
लेकिन ईमानदार होने के लिए, इस बिंदु पर आपको अधिक महत्वपूर्ण कार्य करने के लिए आगे बढ़ना चाहिए। :)
n = n * (-1)
लिखने का एक हास्यास्पद तरीका हैn = -n
; केवल एक अकादमिक भी इसके बारे में सोचेगा। अकेले निरर्थक कोष्ठक जोड़ें।