संक्षिप्त जवाब
पूर्णांक श्रेणी के लिए:
Enumerable#sum रिटर्न (range.max-range.min+1)*(range.max+range.min)/2
Enumerable#inject(:+) हर तत्व पर पुनरावृत्ति।
सिद्धांत
1 के बीच पूर्णांक का योग और nएक त्रिकोणीय संख्या कहा जाता है , और के बराबर है n*(n+1)/2।
के बीच पूर्णांकों का योग nऔर mकी त्रिकोणीय संख्या है mशून्य से की त्रिकोणीय संख्या n-1है, जो के बराबर है m*(m+1)/2-n*(n-1)/2, और लिखा जा सकता है (m-n+1)*(m+n)/2।
रूबी 2.4 में अनगिनत # योग
Enumerable#sumपूर्णांक श्रेणी के लिए उपयोग की गई यह संपत्ति :
if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
if (!memo.block_given && !memo.float_value &&
(FIXNUM_P(beg) || RB_TYPE_P(beg, T_BIGNUM)) &&
(FIXNUM_P(end) || RB_TYPE_P(end, T_BIGNUM))) {
return int_range_sum(beg, end, excl, memo.v);
}
}
int_range_sum इस तरह दिखता है :
VALUE a;
a = rb_int_plus(rb_int_minus(end, beg), LONG2FIX(1));
a = rb_int_mul(a, rb_int_plus(end, beg));
a = rb_int_idiv(a, LONG2FIX(2));
return rb_int_plus(init, a);
जो इसके बराबर है:
(range.max-range.min+1)*(range.max+range.min)/2
उक्त समानता!
जटिलता
इस भाग के लिए @k_g और @ Hynek-Pichi-Vychodil को बहुत-बहुत धन्यवाद!
योग
(1...1000000000000000000000000000000).sum
तीन परिवर्धन, एक गुणन, एक घटाव और एक विभाजन की आवश्यकता होती है।
यह संचालन की एक निरंतर संख्या है, लेकिन गुणन Enumerable#sumएक पूर्णांक सीमा के लिए O ((log n) operations) है, इसलिए O ((log n) operations) है।
इंजेक्षन
(1...1000000000000000000000000000000).inject(:+)
999999999999999999999999999998 परिवर्धन की आवश्यकता है!
जोड़ ओ (लॉग एन) है, इसलिए Enumerable#injectओ (एन लॉग एन) है।
साथ 1E30इनपुट के रूप में, injectके साथ वापस कभी नहीं। सूरज बहुत पहले फट जाएगा!
परीक्षा
यह जांचना आसान है कि रूबी इंटेगर को जोड़ा जा रहा है या नहीं:
module AdditionInspector
def +(b)
puts "Calculating #{self}+#{b}"
super
end
end
class Integer
prepend AdditionInspector
end
puts (1..5).sum
#=> 15
puts (1..5).inject(:+)
# Calculating 1+2
# Calculating 3+3
# Calculating 6+4
# Calculating 10+5
#=> 15
enum.cटिप्पणियों से वास्तव में :
Enumerable#sumमेथड रिडिफाइनमेंट ऑफ मेथड इज़ नॉट द "+"
मेथड्स ऑफ़ मेथड जैसे Integer#+।