लूप समकक्ष नहीं हैं, और आप मुख्य रूप से बड़े पैकेज को थ्रैश कर रहे हैं और इसका for
बनाम while
प्रति से कोई लेना देना नहीं है।
जबकि लूप नोटेशन '$s *= $i
' का उपयोग करता है लेकिन लूप के लिए '$s = $s * $i
' का उपयोग करता है। यह दिखाने के लिए काफी आसान है कि ये समान नहीं हैं। इसके अलावा, एक पाश मायने रखता है; दूसरा गिना जाता है। यह प्रभावित करता है कि संख्याओं को गुणा करने के लिए कितने बड़े हैं। यह दूसरा क्रम प्रभाव है - लेकिन पूरी तरह से नगण्य नहीं है।
[अद्यतन: उप-दूसरे समय के साथ कोड के केवल एक संस्करण को दिखाने के लिए संशोधित किया गया। यह सोचने के लिए एक कमरा है कि प्रिंटिंग समय गणना से बाहर रखा जाना चाहिए; जो चीजों को गड़बड़ कर देता है, इसलिए मुझे परेशान नहीं किया गया है। मैंने पिछले संस्करण में बग तय कर दिया है: लूप 4 लूप 3 जैसा ही था - अब यह नहीं है। मैंने आउटपुट स्वरूपण को भी बढ़ा दिया है (हालांकि उप-सेकेंड हैंडलिंग में सुधार किया जा सकता है - पाठक के लिए एक अभ्यास), और बेहतर 'प्रगति रिपोर्टिंग' है।]
पर एक मैक मिनी (हिमपात तेंदुए 10.6.2) समय परिणाम थे:
Count up $s *= $i: 00:00:12.663337
Count up $s = $s * $i: 00:00:20.686111
Count down $s *= $i: 00:00:14.201797
Count down $s = $s * $i: 00:00:23.269874
स्क्रिप्ट:
use Time::HiRes qw(gettimeofday);
use strict;
use warnings;
use bigint;
use constant factorial_of => 13000;
sub delta_t
{
my($tag, $t1, $t2) = @_;
my($d) = int($t2 - $t1);
my($f) = ($t2 - $t1) - $d;
my($s) = sprintf("%.6f", $f);
$s =~ s/^0//;
printf "%-25s %02d:%02d:%02d%s\n",
$tag, int($d/3600), int(($d % 3600)/60), int($d % 60), $s;
}
my $t1 = gettimeofday;
{
my $n = factorial_of;
my $s = 1;
for (my $i = 2; $i <= $n; $i++)
{
$s *= $i;
}
print "$s\n: Loop 1\n";
}
my $t2 = gettimeofday;
delta_t('Count up $s *= $i:', $t1, $t2);
{
my $n = factorial_of;
my $s = 1;
for (my $i = 2; $i <= $n; $i++)
{
$s = $s * $i;
}
print "$s\n: Loop 2\n";
}
my $t3 = gettimeofday;
delta_t('Count up $s *= $i:', $t1, $t2);
delta_t('Count up $s = $s * $i:', $t2, $t3);
{
my $n = factorial_of;
my $s = 1;
for (my $i = $n; $i > 1; $i--)
{
$s *= $i;
}
print "$s\n: Loop 3\n";
}
my $t4 = gettimeofday;
delta_t('Count up $s *= $i:', $t1, $t2);
delta_t('Count up $s = $s * $i:', $t2, $t3);
delta_t('Count down $s *= $i:', $t3, $t4);
{
my $n = factorial_of;
my $s = 1;
for (my $i = $n; $i > 1; $i--)
{
$s = $s * $i;
}
print "$s\n: Loop 4\n";
}
my $t5 = gettimeofday;
delta_t('Count up $s *= $i:', $t1, $t2);
delta_t('Count up $s = $s * $i:', $t2, $t3);
delta_t('Count down $s *= $i:', $t3, $t4);
delta_t('Count down $s = $s * $i:', $t4, $t5);
और यहाँ की एक और अधिक कॉम्पैक्ट संस्करण है उपरोक्त कोड, 'लूप' के साथ-साथ 'लूप' के परीक्षण के लिए बढ़ाया गया है। यह ज्यादातर समय के मुद्दों से भी निपटता है। एकमात्र चीज जो आदर्श नहीं है (मेरे लिए) यह है कि यह कुछ वैश्विक चर का उपयोग करता है, और मैंने कोड में कोड को थोड़ा सा रेफ्रेंस किया है, इसलिए यह स्क्रॉल बार को ट्रिगर किए बिना एक लाइन पर फिट बैठता है (मेरे डिस्प्ले पर, वैसे भी)। स्पष्ट रूप से, थोड़ा और काम के साथ, परीक्षण को सरणी में लपेटा जा सकता है, ताकि परीक्षण को सामान्य रूप से किया जा सके - सरणी में जानकारी पर टाइमर फ़ंक्शन चलाने वाले सरणी के माध्यम से एक लूप। आदि...यह एक स्मार्ट है - प्रोग्रामिंग का सरल मामला। (यह तथ्यों के मुकाबले फैक्टोरियल के एमडी 5 हैश को प्रिंट करता है, क्योंकि परिणामों की तुलना करना आसान है। इत्यादि ने कुछ त्रुटियों को इंगित किया क्योंकि मैं ऊपर दिए गए कोड को दोबारा कर रहा था। हाँ, एमडी 5 सुरक्षित नहीं है - लेकिन मैं सुरक्षा के लिए यह उपयोग कर रहा हूँ नहीं, बस अनजाने में परिवर्तन को पहचानना)
use Time::HiRes qw(gettimeofday);
use Digest::MD5 qw(md5_hex);
use strict;
use warnings;
use bigint;
use constant factorial_of => 13000;
my ($s, $i);
my $l1 = sub {my($n) = @_; for ($i = 2; $i <= $n; $i++) { $s *= $i; }};
my $l2 = sub {my($n) = @_; for ($i = 2; $i <= $n; $i++) { $s = $s * $i; }};
my $l3 = sub {my($n) = @_; for ($i = $n; $i > 1; $i--) { $s *= $i; }};
my $l4 = sub {my($n) = @_; for ($i = $n; $i > 1; $i--) { $s = $s * $i; }};
my $l5 = sub {my($n) = @_; $i = 2; while ($i <= $n) { $s *= $i; $i++; }};
my $l6 = sub {my($n) = @_; $i = 2; while ($i <= $n) { $s = $s * $i; $i++; }};
my $l7 = sub {my($n) = @_; $i = $n; while ($i > 1) { $s *= $i; $i--; }};
my $l8 = sub {my($n) = @_; $i = $n; while ($i > 1) { $s = $s * $i; $i--; }};
sub timer
{
my($n, $code, $tag) = @_;
my $t1 = gettimeofday;
$s = 1;
&$code(factorial_of);
my $t2 = gettimeofday;
my $md5 = md5_hex($s);
printf "Loop %d: %-33s %09.6f (%s)\n", $n, $tag, $t2 - $t1, $md5;
}
my $count = 1;
timer($count++, $l1, 'for - Count up $s *= $i:');
timer($count++, $l2, 'for - Count up $s = $s * $i:');
timer($count++, $l3, 'for - Count down $s *= $i:');
timer($count++, $l4, 'for - Count down $s = $s * $i:');
timer($count++, $l5, 'while - Count up $s *= $i:');
timer($count++, $l6, 'while - Count up $s = $s * $i:');
timer($count++, $l7, 'while - Count down $s *= $i:');
timer($count++, $l8, 'while - Count down $s = $s * $i:');
उदाहरण आउटपुट (MD5 चेकसम लाइन तोड़ने से बचने के लिए संकुचित - पूरा मूल्य 584b3ab832577fd1390970043efc0ec8
है):
Loop 1: for - Count up $s *= $i: 12.853630 (584b3ab8...3efc0ec8)
Loop 2: for - Count up $s = $s * $i: 20.854735 (584b3ab8...3efc0ec8)
Loop 3: for - Count down $s *= $i: 14.798155 (584b3ab8...3efc0ec8)
Loop 4: for - Count down $s = $s * $i: 23.699913 (584b3ab8...3efc0ec8)
Loop 5: while - Count up $s *= $i: 12.972428 (584b3ab8...3efc0ec8)
Loop 6: while - Count up $s = $s * $i: 21.192956 (584b3ab8...3efc0ec8)
Loop 7: while - Count down $s *= $i: 14.555620 (584b3ab8...3efc0ec8)
Loop 8: while - Count down $s = $s * $i: 23.790795 (584b3ab8...3efc0ec8)
मैं। संबंधित 'फॉर' लूप पर 'थोड़ी' लूप के लिए लगातार एक छोटा (< 1%) जुर्माना देखें, लेकिन मेरे पास अच्छा स्पष्टीकरण नहीं है यह।
आप शायद गलत चीज़ को अनुकूलित करने का प्रयास कर रहे हैं। मैं सोच रहा हूं कि आपको क्यों लगता है कि भाषा का यह विशेष हिस्सा इतना महत्वपूर्ण है? – Ether
उन्हें प्रत्येक बार चलाएं, और संभवतः वे लगभग – CaffGeek
@ चाड के बारे में औसत होंगे, असल में मैंने कोड को दो बार पहले से ही जांच लिया है। उन्होंने एक ही नौकरी खत्म करने के लिए अलग-अलग समय लगाए। मुझे लगता है कि @ जेनाथन लेफ्लर के चित्रण कोड के साथ स्पष्टीकरण बहुत अच्छी समझ में आता है। – Mike