ইনজেকশন (: +) এর চেয়ে যোগফল এত দ্রুত কেন?


129

সুতরাং আমি রুবি ২.৪.০ এ কিছু মানদণ্ড চালিয়ে যাচ্ছি এবং বুঝতে পেরেছিলাম

(1...1000000000000000000000000000000).sum

তত্ক্ষণাত গণনা করে

(1...1000000000000000000000000000000).inject(:+)

এতক্ষণ সময় নেয় যে আমি সবেমাত্র অপারেশনটি বাতিল করে দিয়েছি। আমি এমন ছাপে Range#sumছিলাম যে এটির জন্য একটি নাম ছিল Range#inject(:+)তবে মনে হয় এটি সত্য নয়। সুতরাং কিভাবে sumকাজ করে, এবং কেন এটি এত দ্রুত inject(:+)?

এনবিEnumerable#sum (যা দ্বারা প্রয়োগ করা হয় Range) এর জন্য ডকুমেন্টেশন অলস মূল্যায়ন বা those লাইন বরাবর কিছু সম্পর্কে কিছু বলে না।

উত্তর:


227

সংক্ষিপ্ত উত্তর

একটি পূর্ণসংখ্যার ব্যাপ্তির জন্য:

  • 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

রুবি ২.৪-তে অনুমিত # সমষ্টি

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

পূর্বোক্ত সমতা!

জটিলতা

এই অংশের জন্য @ কে_জি এবং @ হায়েনেক-পিচি-ভ্যাচোডিলকে অনেক ধন্যবাদ!

সমষ্টি

(1...1000000000000000000000000000000).sum তিনটি সংযোজন, একটি গুণ, একটি বিয়োগ এবং একটি বিভাগ প্রয়োজন।

এটি অবিচ্ছিন্ন ক্রিয়াকলাপ, তবে গুণনটি হ'ল ((লগ এন) ²), সুতরাং Enumerable#sumপূর্ণসংখ্যার ব্যাপ্তির জন্য ও ((লগ এন)।) Is

উদ্বুদ্ধ করা

(1...1000000000000000000000000000000).inject(:+)

9999999999999999999999999999998 সংযোজন প্রয়োজন!

সংযোজন হ'ল ও (লগ এন), 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#+


17
আপনি যদি সঠিক সূত্রটি ব্যবহার করেন তবে বিভিন্ন সংখ্যার যোগফলের গণনা করা তুচ্ছ এবং আপনি যদি এটির পুনরাবৃত্তি করে যান তবে উদ্দীপকটি হ'ল এটি একটি সত্যই অপটিমাইজেশন। এটি একাধিক সংযোজন ক্রিয়াকলাপ হিসাবে গুণাকে বাস্তবায়নের চেষ্টা করার মতো।
tadman

তাহলে পারফরম্যান্স বুস্ট n+1কেবল রেঞ্জের জন্য ? আমার কাছে ২.৪ ইনস্টল নেই বা আমি নিজে যাচাই করে নেব তবে মৌলিক সংযোজন দ্বারা পরিচালিত অন্যান্য প্রচুর পরিমাণে অবজেক্টগুলি হ'ল তারা প্রোক চিহ্নের ওভারহেডকে মাইনাসে করবে inject(:+)
ইঞ্জিনিয়ারস্মিনিকি

8
পাঠক, আপনার হাই স্কুলের গণিত থেকে রিকল n, n+1, n+2, .., mএকটি গঠন করে গাণিতিক সিরিজ যার সমষ্টি সমান (m-n+1)*(m+n)/2। একইভাবে, এর সমষ্টি জ্যামিতিক সিরিজের , n, (α^1)n, (α^2)n, (α^3)n, ... , (α^m)n। একটি বদ্ধ-ফর্ম এক্সপ্রেশন থেকে গণনা করা যেতে পারে।
ক্যারি সোভেল্যান্ড

4
numbers start {nitpick ume গণনাযোগ্য # যোগফল হ'ল ((লগ এন) ^ 2) এবং ইনজেকশন হ'ল O (n লগ এন) যখন আপনার সংখ্যাগুলি সীমাহীন করার অনুমতি দেওয়া হয়। \ শেষ {নিটপিক}
কে_জি

6
@ এলিস্যাডোফ: এর অর্থ সত্যই বড় সংখ্যা। এর অর্থ সংখ্যাগুলি যা আর্কিটেকচার শব্দের সাথে খাপ খায় না তার অর্থ সিপিইউ কোরতে একটি নির্দেশ এবং একটি ক্রিয়াকলাপ দ্বারা গুণ করা যায় না। আকারের সংখ্যা N লোগুলি দ্বারা এনকোড করা যেতে পারে N বিটস তাই সংযুক্তি O (লগএন) অপারেশন এবং গুণনটি হ'ল ((লগএন) ^ 2) তবে ও ((লগএন) ^ 1.585) (করাসুবা) বা এমনকি ও (লগএন *) হতে পারে লগ (logN) * লগ (লগ (logN)) (FFT)।
Hynek -Pichi- Vychodil
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.