अनपेक्षित परिणाम जब व्याख्या की गई भाषाओं पर बहुत बड़े पूर्णांक के साथ काम करते हैं


192

मैं योग की कोशिश कर 1 + 2 + ... + 1000000000रहा हूं, लेकिन मुझे PHP और Node.js में अजीब परिणाम मिल रहे हैं ।

पीएचपी

$sum = 0;
for($i = 0; $i <= 1000000000 ; $i++) {
    $sum += $i;
}
printf("%s", number_format($sum, 0, "", ""));   // 500000000067108992

Node.js

var sum = 0;
for (i = 0; i <= 1000000000; i++) {
    sum += i ;
}
console.log(sum); // 500000000067109000

सही उत्तर का उपयोग करके गणना की जा सकती है

1 + 2 + ... + n = n(n+1)/2

सही उत्तर = 500000000500000000 , इसलिए मैंने दूसरी भाषा आज़माने का फैसला किया।

जाओ

var sum , i int64
for i = 0 ; i <= 1000000000; i++ {
    sum += i
}
fmt.Println(sum) // 500000000500000000

लेकिन यह ठीक काम करता है! तो मेरे PHP और Node.js कोड में क्या गलत है?

शायद यह व्याख्या की गई भाषाओं की समस्या है, और इसीलिए यह गो जैसी संकलित भाषा में काम करती है? यदि हां, तो क्या पायथन और पर्ल जैसी अन्य व्याख्या की गई भाषाओं में भी यही समस्या होगी?


36
आपको इसकी आवश्यकता है: php.net/manual/en/book.bc.php , वरना IEEE 754 के खिलाफ आपके सिर को तब तक मारेंगे , जब तक कि नर्क फ़्रीज न हो जाए।
tereško

5
PHP में बड़ी संख्या (यानी 64-बिट) को संभालने के लिए, इस मामले में gmp_add () में GMP फ़ंक्शन का उपयोग करें।
जेफरी

113
सुपर दक्षता के लिए, आपके छोरों को वास्तव में 0. के बजाय 1 पर शुरू होना चाहिए: पी
ग्राहम बोरलैंड

55
योग (1 से एन) = (एन / 2) * (एन + 1)
फोंग

5
@ बाबा 0 आपकी गणना के लिए बहुत ही शानदार है, इसलिए 0 से 0. को जोड़ने के लिए लूप की अतिरिक्त पुनरावृत्ति की आवश्यकता नहीं है
ब्रायन वारशॉ

जवाबों:


155

अजगर काम करता है:

>>> sum(x for x in xrange(1000000000 + 1))
500000000500000000

या:

>>> sum(xrange(1000000000+1))
500000000500000000

पायथन का intऑटो एक पायथन को बढ़ावा देता है longजो मनमाना परिशुद्धता का समर्थन करता है। यह 32 या 64 बिट प्लेटफार्मों पर सही उत्तर देगा।

इसे प्लेटफ़ॉर्म की थोड़ी चौड़ाई से 2 गुना अधिक ताकत से देखा जा सकता है:

>>> 2**99
633825300114114700748351602688L

आप प्रदर्शित कर सकते हैं (पायथन के साथ) कि PHP में आपके द्वारा प्राप्त किए जा रहे गलत मान हैं क्योंकि PHP एक फ्लोट को बढ़ावा दे रहा है जब मान 2 ** 32-1 से अधिक होते हैं:

>>> int(sum(float(x) for x in xrange(1000000000+1)))
500000000067108992

क्या आपने इसे 32 या 64 बिट सिस्टम पर चलाया है?
बाबा

4
यह परवाह किए बिना काम करना चाहिए (32 बनाम 64 बिट) चूंकि पायथन इन्टस ऑटो ओवरफ्लो के बजाय मनमानी परिशुद्धता को बढ़ावा देता है। थोडा अधिक समय लग सकता है।
dawg

3
किसी भी प्रणाली पर पायथन इस मामले में काम करेगा, क्योंकि अजगर जरूरत पड़ने पर स्वचालित रूप से लंबे पूर्णांक पर स्विच करता है। और अगर यह पर्याप्त नहीं है, तो यह बड़े पूर्णांक पर भी स्विच करेगा।
आलोक सिंघल

12
@ 0x499602D2: यह थोड़े कठोर है। ओपी ने खुद इसे वोट किया। उन्होंने विशेष रूप से पूछा कि क्या यह पायथन पर इसी तरह की समस्या थी। उत्तर, नहीं, यह नहीं है। कोड यह दिखाने के लिए कि यह नहीं है। WTH?
dgg

10
पायथन का उदाहरण बहुत लंबा है, बस योग का उपयोग करें (xrange (int (1e9) +1)) (.... पुनरावृत्तियों पर योग)
जेसन मॉर्गन

101

आपका गो कोड सटीक उत्तर देने के लिए पर्याप्त बिट्स के साथ पूर्णांक अंकगणित का उपयोग करता है। PHP या Node.js को कभी नहीं छुआ, लेकिन परिणामों से मुझे संदेह है कि फ़्लोटिंग पॉइंट नंबरों का उपयोग करके गणित किया जाता है और इस प्रकार इस परिमाण की संख्याओं के लिए सटीक नहीं होने की उम्मीद की जानी चाहिए।


46
हां। If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.- php.net/manual/en/language.types.integer.php
Nate

3
और NodeJS (और सामान्य रूप से जावास्क्रिप्ट) में सभी अंकगणित संचालन (बिट संचालन को छोड़कर) व्यवहार करते हैं जैसे कि वे फ्लोटिंग पॉइंट संख्याओं के साथ किए गए थे। चाहे वे वास्तव में हों या नहीं, व्यक्तिगत जावास्क्रिप्ट इंजनों के निर्णयों के अधीन एक अंडर-हुड अंतर है।
पीटर ओल्सन

13
जावास्क्रिप्ट के विनिर्देश में, कोई पूर्णांक प्रकार नहीं है। सभी नंबर फ्लोटिंग पॉइंट हैं।
toasted_flakes

8
@grasGendarme हैं। ES5 कल्पना विभिन्न पूर्णांक रूपांतरणों और जनादेशों को निर्दिष्ट करती है जिन्हें उन्हें बिटवाइज़ शिफ्ट्स में कहा जाता है । यह कि पर्दे के पीछे कहने के लिए , जावास्क्रिप्ट में पूर्णांक प्रकार का उपयोग किया जाता है, लेकिन सभी अंकगणित ऑपरेटर अपने संचालकों को उनके साथ कुछ भी करने से पहले फ्लोटिंग पॉइंट संख्या में बदल देते हैं (संकलक अनुकूलन को रोकते हैं)।
पीटर ओल्सन

2
यहाँ कोड मुझे लगता है कि इसका गड़बड़ है क्योंकि मैं float64 और int64 का उपयोग नहीं किया है .. बस यह 32 या 64 बिट्स के साथ कुछ नहीं करना है की पुष्टि की
बाबा

45

कारण यह है कि आपके पूर्णांक चर का sumमान अधिकतम मूल्य से अधिक है। और sumआपको प्राप्त फ्लोट-पॉइंट अंकगणित का परिणाम होता है जिसमें चक्कर लगाना शामिल होता है। चूंकि अन्य उत्तरों में सटीक सीमाओं का उल्लेख नहीं था, इसलिए मैंने इसे पोस्ट करने का फैसला किया।

PHP के लिए अधिकतम पूर्णांक मान:

  • 32-बिट संस्करण 2147483647 है
  • 64-बिट संस्करण 9223372036854775807 है

तो इसका मतलब है कि या तो आप 32 बिट सीपीयू या 32 बिट ओएस या पीएचपी के 32 बिट संकलित संस्करण का उपयोग कर रहे हैं। इसका उपयोग करके पाया जा सकता है PHP_INT_MAXsumयदि आप इसे 64 बिट मशीन पर करते हैं तो सही गणना की जाएगी।

जावास्क्रिप्ट में अधिकतम पूर्णांक मान 9007199254740992 है । आपके साथ काम करने वाला सबसे बड़ा सटीक अभिन्न मूल्य 2 53 (इस प्रश्न से लिया गया ) है। sumइस सीमा से अधिक।

यदि पूर्णांक मान इन सीमाओं से अधिक नहीं है, तो आप अच्छे हैं। अन्यथा आपको मनमाने ढंग से सटीक पूर्णांक पुस्तकालयों की तलाश करनी होगी।


28

यहाँ उत्तर में C, पूर्णता के लिए है:

#include <stdio.h>

int main(void)
{
    unsigned long long sum = 0, i;

    for (i = 0; i <= 1000000000; i++)    //one billion
        sum += i;

    printf("%llu\n", sum);  //500000000500000000

    return 0;
}

इस मामले में कुंजी C99 के long long डेटा प्रकार का उपयोग कर रही है । यह सबसे बड़ा आदिम भंडारण सी प्रदान करता है जिसे प्रबंधन कर सकता है और यह वास्तव में, वास्तव में तेजी से चलता है । long longप्रकार भी सबसे किसी भी 32 या 64-बिट मशीन पर काम करेंगे।

एक चेतावनी है: Microsoft द्वारा प्रदान किए गए संकलक स्पष्ट रूप से 14 वर्ष पुराने C99 मानक का समर्थन नहीं करते हैं, इसलिए विजुअल स्टूडियो में चलाने के लिए यह एक क्रेपशॉट है।


3
MSVC ++ एक C ++ कंपाइलर है, और C ++ long longC ++ 11 मानक में मिला है। यह कुछ वर्षों के लिए MSVC ++ और g ++ एक्सटेंशन रहा है, हालांकि।
एमएसलेट्स

1
@MSalters तो एक C ++ फीचर होने के नाते यह वास्तव में किसी को भी सीधा C प्रोग्राम संकलित करने में मदद नहीं करेगा। मैंने कभी भी C से C ++ में स्विच करने की कोशिश नहीं की, इसलिए मुझे नहीं पता कि क्या यह वर्कअराउंड वास्तव में काम करेगा।
साइबरस्कुल

19
और अच्छी तरह से, अनुकूलन के साथ जीसीसी या movabsq $500000000500000000, %rsi
क्लेंग

3
बस gcc -O3या clang -O3। मैं विशिष्ट अनुकूलन का नाम नहीं जानता। मूल रूप से संकलक ने नोटिस किया कि लूप का परिणाम किसी भी तर्क पर निर्भर नहीं करता है, और संकलन समय पर इसकी गणना करता है।
Tor Klingberg

1
C99 लंबे लंबे का न्यूनतम आकार 64 बिट्स है और जहां तक ​​मुझे पता है कि 32-बिट और 64-बिट प्लेटफॉर्म दोनों पर 64 बिट है। मैंने क्वाड या ऑक्टो इन्ट्स के लिए सामान्य समर्थन नहीं देखा है।
डेविन लेन

21

मेरा अनुमान है कि जब राशि एक देशी int(2 31 -1 = 2,147,483,647) की क्षमता से अधिक हो जाती है , तो Node.js और PHP एक फ्लोटिंग पॉइंट प्रतिनिधित्व में बदल जाते हैं और आपको गोल-गोल त्रुटियां होने लगती हैं। गो जैसी भाषा संभवतः एक पूर्णांक फॉर्म (जैसे, 64-बिट पूर्णांक) को यथासंभव लंबे समय तक चिपकाने की कोशिश करेगी (यदि वास्तव में, यह उस से शुरू नहीं हुई थी)। चूंकि उत्तर 64-बिट पूर्णांक में फिट बैठता है, इसलिए गणना सटीक है।


Node.js में स्पष्ट रूप से एक इंट प्रकार नहीं है। यह एक फ्लोट प्रकार में काम कर रहा है।
ग्रेफेड

@ ग्रेफेड - हाँ, मुझे लगता है कि यह सभी EcmaScript-compliant वातावरण के लिए सही है।
टेड हॉप

ऐसा नहीं है (2 ** 31 - 1)?
ज़ाचरी हंटर

@ZacharyHunter - वास्तव में यह है। उस त्रुटि को पकड़ने के लिए धन्यवाद।
टेड हॉप

19

पर्ल स्क्रिप्ट हमें अपेक्षित परिणाम देती है:

use warnings;
use strict;

my $sum = 0;
for(my $i = 0; $i <= 1_000_000_000; $i++) {
    $sum += $i;
}
print $sum, "\n";  #<-- prints: 500000000500000000

3
क्या आपने इसे 32 या 64 बिट सिस्टम पर चलाया है?
बाबा

2
यह 64 बिट सिस्टम पर निष्पादित किया गया था
मिगुएल प्रेज़

3
4.99999999067109e+017पर्ल पर v5.16.1 MSWin32-x86।
22

7
यदि आपको वास्तव में बड़ी संख्या की आवश्यकता है, bignumया का उपयोग करें bigint। दोनों कोर मॉड्यूल हैं, अर्थात्, वे पर्ल v5.8.0 या उच्चतर के साथ स्थापित हैं। देखें http://perldoc.perl.org/bignum.htmlऔरhttp://perldoc.perl.org/bigint.html
shawnhcorey

मैं एक 32-बिट पीपीसी मैक पर इसे चलाने के लिए 500000000500000000 मिला, पर्ल 5.12.4 पर चल रहा था।
साइबरस्कूल

17

इसका उत्तर "आश्चर्यजनक" सरल है:

पहला - जैसा कि आप में से अधिकांश जानते होंगे - एक 32-बिट पूर्णांक −2,147,483,648 से लेकर 2,147,483,647 तक होता है । तो, क्या होगा यदि PHP का परिणाम होता है, जो कि इससे LARGER है?

आमतौर पर, एक व्यक्ति को तत्काल "अतिप्रवाह" की उम्मीद होती है, जिससे 2,147,483,647 + 1 a2,147,483,648 हो जाते हैं । हालांकि, यह मामला नहीं है। यदि PHP एक बड़ी संख्या का सामना करता है, तो यह INT के बजाय FLOAT लौटाता है।

यदि PHP पूर्णांक प्रकार की सीमाओं से परे एक संख्या का सामना करता है, तो इसे एक फ्लोट के रूप में व्याख्या किया जाएगा। इसके अलावा, एक ऑपरेशन जिसके परिणामस्वरूप पूर्णांक प्रकार की सीमा से परे एक संख्या होती है, इसके बजाय एक फ्लोट लौटाएगा।

http://php.net/manual/en/language.types.integer.php

यह कहा गया है, और यह जानकर कि PHP FLOAT कार्यान्वयन IEEE 754 दोहरे परिशुद्धता प्रारूप का अनुसरण कर रहा है, इसका मतलब है, कि PHP 52 बिट तक की संख्या से निपटने में सक्षम है, बिना सटीकता खोए। (32-बिट सिस्टम पर)

तो, उस बिंदु पर, जहां आपका योग 9,007,199,254,740,992 (जो 2 ^ 53 है ) हिट करता है , PHP मैथ्स द्वारा लौटाया गया फ्लोट मान अब पर्याप्त रूप से सटीक नहीं होगा।

E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000000\"); echo number_format($x,0);"

9.007.199.254.740.992

E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000001\"); echo number_format($x,0);"

9.007.199.254.740.992

E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000010\"); echo number_format($x,0);"

9.007.199.254.740.994

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

अब से, डिफ़ॉल्ट डेटा-प्रकारों के साथ काम करने पर पूरा गणित गलत हो जाएगा।

• क्या अन्य व्याख्यात्मक भाषा जैसे कि पायथन या पर्ल के लिए भी यही समस्या है?

मुझे ऐसा नहीं लगता। मुझे लगता है कि यह उन भाषाओं की समस्या है जिनकी कोई प्रकार-सुरक्षा नहीं है। हालांकि एक पूर्णांक ओवरफ्लो जैसा कि ऊपर उल्लेख किया गया है, हर भाषा में होता है जो निश्चित डेटा प्रकारों का उपयोग करता है, बिना टाइप-सुरक्षा वाली भाषाएं इसे अन्य डेटाटिप्स के साथ पकड़ने की कोशिश कर सकती हैं। हालांकि, एक बार जब उन्होंने अपनी "प्राकृतिक" (सिस्टम-दी गई) सीमा को मार दिया - वे कुछ भी वापस कर सकते हैं, लेकिन सही परिणाम।

हालाँकि, प्रत्येक भाषा में ऐसे परिदृश्य के लिए अलग थ्रेडिंग हो सकती है।


15

अन्य उत्तर पहले से ही बताए गए हैं कि यहां क्या हो रहा है (हमेशा की तरह सटीकता से तैरते हुए)।

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

अन्य समाधान एक समरूप एल्गोरिथ्म का उपयोग करना है जो सटीक समस्या के बारे में जानता है और इसके चारों ओर काम करता है। नीचे आपको एक ही योग मिलता है, पहले 64 बिट पूर्णांक के साथ, फिर 64 बिट फ्लोटिंग पॉइंट के साथ और फिर फ़्लोटिंग पॉइंट का उपयोग करते हुए, लेकिन कहन योग एल्गोरिथ्म के साथ

C # में लिखा है, लेकिन अन्य भाषाओं के लिए भी यही है।

long sum1 = 0;
for (int i = 0; i <= 1000000000; i++)
{
    sum1 += i ;
}
Console.WriteLine(sum1.ToString("N0"));
// 500.000.000.500.000.000

double sum2 = 0;
for (int i = 0; i <= 1000000000; i++)
{
    sum2 += i ;
}
Console.WriteLine(sum2.ToString("N0"));
// 500.000.000.067.109.000

double sum3 = 0;
double error = 0;
for (int i = 0; i <= 1000000000; i++)
{
    double corrected = i - error;
    double temp = sum3 + corrected;
    error = (temp - sum3) - corrected;
    sum3 = temp;
}
Console.WriteLine(sum3.ToString("N0"));
//500.000.000.500.000.000

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


@ बाबा यह ओपी में Node.js / JavaScript के समान है। क्यों 500000000067109000 बनाम 500000000067108992… पता नहीं।
linac

शायद बाबा हजार विभाजकों के लिए डॉट्स के उपयोग से अंतर्ग्रथित है: अंग्रेजी आमतौर पर कॉमा की अपेक्षा करती है। आप अंडरस्कोर का उपयोग अधिक तटस्थ माध्य के रूप में भी कर सकते हैं।
didierc

14

यदि आपके पास 32-बिट PHP है, तो आप इसे बीसी के साथ गणना कर सकते हैं :

<?php

$value = 1000000000;
echo bcdiv( bcmul( $value, $value + 1 ), 2 );
//500000000500000000

जावास्क्रिप्ट में आपको मनमानी संख्या पुस्तकालय का उपयोग करना होगा, उदाहरण के लिए BigInteger :

var value = new BigInteger(1000000000);
console.log( value.multiply(value.add(1)).divide(2).toString());
//500000000500000000

यहां तक ​​कि गो और जावा जैसी भाषाओं के साथ, आपको अंततः मनमानी संख्या पुस्तकालय का उपयोग करना होगा, आपकी संख्या 64-बिट के लिए पर्याप्त छोटी लेकिन 32-बिट के लिए बहुत अधिक है।


12

रूबी में:

sum = 0
1.upto(1000000000).each{|i|
  sum += i
}
puts sum

प्रिंट करता है 500000000500000000, लेकिन मेरे 2.6 गीगाहर्ट्ज इंटेल आई 7 पर एक अच्छा 4 मिनट लगता है।


मैग्नस और जोंटी के पास अधिक रूबी समाधान है:

1.upto(1000000000).inject(:+)

एक बेंचमार्क चलाने के लिए:

$ time ruby -e "puts 1.upto(1000000000).inject(:+)"
ruby -e "1.upto(1000000000).inject(:+)"  128.75s user 0.07s system 99% cpu 2:08.84 total

10
1.upto (1000000000) .inject (: +)
Magnuss

@Magnuss: यही मैंने सोचा था कि मैंने पहली बार कोशिश की, लेकिन यह एक बड़े पैमाने पर स्मृति रिसाव का कारण बना। तुम्हारा काम लगता है ...
cgenco

11

मैं बड़े पूर्णांक सामान के लिए नोड-बिगिंट का उपयोग करता हूं:
https://github.com/substack/node-bigint

var bigint = require('bigint');
var sum = bigint(0);
for(var i = 0; i <= 1000000000; i++) { 
  sum = sum.add(i); 
}
console.log(sum);

यह कुछ ऐसा नहीं है जो इस सटीक परीक्षण के लिए मूल 64-बिट सामान का उपयोग कर सकता है, लेकिन यदि आप 64-बिट से बड़ी संख्या में आते हैं, तो यह हुड के नीचे libgmp का उपयोग करता है, जो कि वहाँ से बाहर तेजी से मनमानी परिशुद्धता पुस्तकालयों में से एक है।


4

रूबी में उम्र ले ली, लेकिन सही जवाब देता है:

(1..1000000000).reduce(:+)
 => 500000000500000000 

4

Php में सही परिणाम प्राप्त करने के लिए मुझे लगता है कि आपको BC गणित संचालकों का उपयोग करने की आवश्यकता होगी: http://php.net/manual/en/ref.bc.php

यहाँ स्काला में इसका सही उत्तर है। आपको Longs का उपयोग करना होगा अन्यथा आप संख्या को ओवरफ्लो करते हैं:

println((1L to 1000000000L).reduce(_ + _)) // prints 500000000500000000

3

वहाँ वास्तव में इस समस्या के लिए एक अच्छा चाल है।

इसके बजाय 1-100 मान लिया गया था।

1 + 2 + 3 + 4 + ... + 50 +

100 + 99 + 98 + 97 + ... + 51

= (101 + 101 + 101 + 101 + ... + 101) = 101 * 50

सूत्र:

एन = 100 के लिए: आउटपुट = एन / 2 * (एन + 1)

N = 1e9 के लिए: आउटपुट = N / 2 * (N + 1)

यह उस सभी डेटा के माध्यम से लूपिंग की तुलना में बहुत तेज है। आपका प्रोसेसर इसके लिए आपको धन्यवाद देगा। और यहाँ इस समस्या के बारे में एक दिलचस्प कहानी है:

http://www.jimloy.com/algebra/gauss.htm


11
क्या आपको लगता है कि दो बार किसी भी पुल को पार किए बिना, कैलिनिनग्राद में प्रागेल में हर पुल पर चलना संभव हो सकता है? कई लोगों ने कोशिश की और असफल रहे, लेकिन किसी ने अभी तक स्थापित नहीं किया है कि यह असंभव है। यह एक चुनौती की तरह लगता है जिसे आप हल करने के लिए विशिष्ट रूप से योग्य होंगे।
jwg

3

यह पूर्णांक कलाकारों को मजबूर करके PHP में उचित परिणाम देता है।

$sum = (int) $sum + $i;

3

आम लिस्प सबसे तेजी से व्याख्या की गई * भाषाओं में से एक है और डिफ़ॉल्ट रूप से मनमाने ढंग से बड़े पूर्णांकों को सही ढंग से संभालती है। SBCL के साथ लगभग 3 सेकंड लगते हैं :

* (time (let ((sum 0)) (loop :for x :from 1 :to 1000000000 :do (incf sum x)) sum))

Evaluation took:
  3.068 seconds of real time
  3.064000 seconds of total run time (3.044000 user, 0.020000 system)
  99.87% CPU
  8,572,036,182 processor cycles
  0 bytes consed

500000000500000000
  • व्याख्या करके, मेरा मतलब है, मैंने इस कोड को REPL से चलाया, SBCL ने इसे तेजी से चलाने के लिए आंतरिक रूप से कुछ JITing किया होगा, लेकिन तुरंत कोड चलाने का गतिशील अनुभव समान है।

के रूप में सरलीकृत किया जा सकता है (समय (x 1 से 1000000000 योग x के लिए लूप))। मैंने घोषणा को जोड़कर ~ 5x गति प्राप्त की: (समय (स्थानीय रूप से घोषित करें (अनुकूलन (गति 3)) (सुरक्षा 0))) - 1 से 1000000000 की राशि i- प्रकार के लिए लूप (i- प्रकार के फिक्सनम))
huaiyuan

यह गलत है। आप अन्य भाषाओं से अंधे मत बनो! लिस्प में इसे लिखने का सही तरीका है: (डीफ़न सम-से-1-टू-एन (n) (/ (* n (1+ n)) 2)) (समय-सम-से-1-टू-एन 1000000000)) को चलाने के लिए 14 माइक्रोसेकंड (0.000014 सेकंड) लगे। उस अवधि के दौरान और के साथ 4 उपलब्ध सीपीयू कोर, 0 माइक्रोसेकंड (०.०००००० सेकंड) उपयोगकर्ता मोड में खर्च किया गया 0 माइक्रोसेकंड (०.०००००० सेकंड) प्रणाली मोड में खर्च किया गया -> 500000000500000000
informatimago

@informatimago: यह गलत नहीं है। मैं प्रश्न की अनिवार्य लूप शैली की नकल कर रहा था और जैसा कि कई ने बताया है, प्रश्न में उल्लेख है कि गणना करने का एक आसान तरीका है। Chillax।
पोस्टफुटुरिस्ट

3

मेरे पास @ postfuturist के कॉमन लिस्प उत्तर पर टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है, लेकिन इसे मेरे मशीन पर SBCL 1.1.8 के साथ ~ 500ms में पूरा करने के लिए अनुकूलित किया जा सकता है:

CL-USER> (compile nil '(lambda () 
                        (declare (optimize (speed 3) (space 0) (safety 0) (debug 0) (compilation-speed 0))) 
                        (let ((sum 0))
                          (declare (type fixnum sum))
                          (loop for i from 1 to 1000000000 do (incf sum i))
                          sum)))
#<FUNCTION (LAMBDA ()) {1004B93CCB}>
NIL
NIL
CL-USER> (time (funcall *))
Evaluation took:
  0.531 seconds of real time
  0.531250 seconds of total run time (0.531250 user, 0.000000 system)
  100.00% CPU
  1,912,655,483 processor cycles
  0 bytes consed

500000000500000000

3

रैकेट v 5.3.4 (एमबीपी; एमएस में समय):

> (time (for/sum ([x (in-range 1000000001)]) x))
cpu time: 2943 real time: 2954 gc time: 0
500000000500000000

1
एक बार जब मैंने तुम्हारा ध्यान दिया, तो मेरे जवाब को 6 मिनट बाद हटा दिया गया। :)
ग्रेग Hendershott

3

Rebol में ठीक काम करता है:

>> sum: 0
== 0

>> repeat i 1000000000 [sum: sum + i]
== 500000000500000000

>> type? sum
== integer!

यह Rebol 3 का उपयोग कर रहा था जो 32 बिट संकलित होने के बावजूद 64-बिट पूर्णांक का उपयोग करता है (Rebol 2 के विपरीत जो 32 बिट पूर्णांक का उपयोग करता है)


3

मैं देखना चाहता था कि सीएफ स्क्रिप्ट में क्या हुआ था

<cfscript>
ttl = 0;

for (i=0;i LTE 1000000000 ;i=i+1) {
    ttl += i;
}
writeDump(ttl);
abort;
</cfscript>

मुझे 5.00000000067E + 017 मिले

यह एक बहुत साफ प्रयोग था। मुझे पूरा यकीन है कि मैं अधिक प्रयास के साथ इसे थोड़ा बेहतर कोडित कर सकता था।


3

ActivePerl v5.10.1 32 बिट विंडो पर, Intel core2duo 2.6:

$sum = 0;
for ($i = 0; $i <= 1000000000 ; $i++) {
  $sum += $i;
}
print $sum."\n";

परिणाम: 5 मिनट में 5.00000000067109e + 017।

"यूज़ बिगिंट" स्क्रिप्ट के साथ दो घंटे काम किया, और अधिक काम किया, लेकिन मैंने इसे रोक दिया। बहुत धीमा।


क्या कोई इस बात की पुष्टि कर सकता है कि वास्तव में कितने समय से कई बड़े निशान लग रहे हैं?
jwg

3

पूर्णता के लिए, क्लोजर में (सुंदर लेकिन बहुत कुशल नहीं):

(reduce + (take 1000000000 (iterate inc 1))) ; => 500000000500000000

1
उपयोगी का एकमात्र छोटा सा हिस्सा है कि $ MY_FAVOURITE_LANGUAGE के पास उत्तर है यदि वे परिणाम प्रदान करते हैं ...
jwg

@jwg हाँ, मुझे खेद है कि लाइन का अंत - अद्यतन उत्तर याद आ गया।
कालासाद

3

AWK:

BEGIN { s = 0; for (i = 1; i <= 1000000000; i++) s += i; print s }

PHP के समान गलत परिणाम उत्पन्न करता है:

500000000067108992

ऐसा लगता है कि संख्या के वास्तव में बड़े होने पर AWK फ्लोटिंग पॉइंट का उपयोग करता है, इसलिए कम से कम उत्तर सही क्रम-परिमाण है।

टेस्ट रन:

$ awk 'BEGIN { s = 0; for (i = 1; i <= 100000000; i++) s += i; print s }'
5000000050000000
$ awk 'BEGIN { s = 0; for (i = 1; i <= 1000000000; i++) s += i; print s }'
500000000067108992

2

श्रेणी की अन्य व्याख्या की गई भाषा:

Tcl:

यदि Tcl 8.4 या अधिक पुराने का उपयोग करते हुए यह निर्भर करता है कि क्या इसे 32 या 64 बिट के साथ संकलित किया गया था। (8.4 जीवन का अंत है)।

यदि Tcl 8.5 या नए का उपयोग करना जिसमें बड़े पूर्णांक हैं, तो यह सही परिणाम प्रदर्शित करेगा।

proc test limit {
    for {set i 0} {$i < $limit} {incr i} {
        incr result $i
    }
    return $result
}
test 1000000000 

मैंने इसे बाइट संकलित करने के लिए एक परीक्षण के अंदर रखा।


2

PHP कोड के लिए, उत्तर यहाँ है :

एक पूर्णांक का आकार प्लेटफ़ॉर्म-निर्भर है, हालांकि लगभग दो बिलियन का अधिकतम मूल्य सामान्य मूल्य है (जो कि 32 बिट्स पर हस्ताक्षर किया गया है)। 64-बिट प्लेटफॉर्म का आमतौर पर अधिकतम मूल्य 9E18 होता है। PHP अहस्ताक्षरित पूर्णांक का समर्थन नहीं करता है। पूर्णांक आकार को निरंतर PHP_INT_SIZE और PHP 4.4.0 और PHP 5.0.5 के बाद से निरंतर PHP_INT_MAX का उपयोग करके अधिकतम मूल्य निर्धारित किया जा सकता है।


2

बंदरगाह:

proc Main()

   local sum := 0, i

   for i := 0 to 1000000000
      sum += i
   next

   ? sum

   return

में परिणाम 500000000500000000। (दोनों विंडो / mingw / x86 और osx / clang / x64 पर)


2

एर्लांग कार्य:

from_sum(From,Max) ->
    from_sum(From,Max,Max).
from_sum(From,Max,Sum) when From =:= Max ->
    Sum;
from_sum(From,Max,Sum) when From =/= Max -> 
    from_sum(From+1,Max,Sum+From).

परिणाम: 41> बेकार: from_sum (1,1000000000)। 500000000500000000


2

मजेदार बात, PHP 5.5.1 499999999500000000 (~ 30 के दशक में) देता है, जबकि Dart2Js 500000000067109000 (जो उम्मीद की जाती है, क्योंकि यह JS है जो निष्पादित हो जाता है) देता है। सीएलआई डार्ट सही उत्तर देता है ... तुरन्त।


2

Erlang अपेक्षित परिणाम भी देता है।

sum.erl:

-module(sum).
-export([iter_sum/2]).

iter_sum(Begin, End) -> iter_sum(Begin,End,0).
iter_sum(Current, End, Sum) when Current > End -> Sum;
iter_sum(Current, End, Sum) -> iter_sum(Current+1,End,Sum+Current).

और इसका उपयोग करते हुए:

1> c(sum).
{ok,sum}
2> sum:iter_sum(1,1000000000).
500000000500000000

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