অনুবাদিত ভাষাগুলিতে খুব বড় পূর্ণসংখ্যার সাথে কাজ করার সময় অপ্রত্যাশিত ফলাফল


192

আমি যোগফল পেতে চেষ্টা 1 + 2 + ... + 1000000000করছি, কিন্তু আমি পিএইচপি এবং নোড.জেএস এ মজার ফলাফল পাচ্ছি ।

পিএইচপি

$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

সঠিক উত্তর = 50000000050000000000 , তাই আমি অন্য ভাষা চেষ্টা করার সিদ্ধান্ত নিয়েছি।

যাওয়া

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

তবে এটা ঠিক কাজ করে! তাহলে আমার পিএইচপি এবং নোড.জেএস কোডটিতে কী ভুল?

সম্ভবত এটি ব্যাখ্যা করা ভাষার সমস্যা, এবং সে কারণেই এটি গোয়ের মতো সংকলিত ভাষায় কাজ করে? যদি তা হয়, তবে পাইথন এবং পার্লের মতো অন্য ব্যাখ্যা করা ভাষাগুলিতেও কি একই সমস্যা হবে?


36
আপনার এটি দরকার: php.net/manual/en/book.bc.php , অথবা অন্যথায় আপনি আইইইই 754 এর বিরুদ্ধে আপনার মাথা ঘায়েল করবেন যতক্ষণ না জাহান্নাম স্থির হয়ে যায়।
tereško

5
পিএইচপিতে (যেমন 64৪-বিট) বড় সংখ্যক পরিচালনা করার জন্য, জিএমপি ফাংশনগুলি ব্যবহার করুন, এই ক্ষেত্রে gmp_add ()।
জেফ্রি

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

আপনি (পাইথনের সাথে) প্রমাণ করতে পারেন যে পিএইচপি-তে আপনি যে ভ্রান্ত মানগুলি পেয়ে যাচ্ছেন তা হ'ল পিএইচপি একটি ভাসমান হিসাবে প্রচার করছে যখন মানগুলি 2 ** 32-1 এর চেয়ে বেশি হয়:

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

আপনি 32 বা 64 বিট সিস্টেমে এটি চালিয়েছেন?
বাবা

4
এটি নির্বিশেষে (32 বনাম 64 বিট) কাজ করা উচিত যেহেতু পাইথন ইনস অটো ওভারফ্লোয়ের পরিবর্তে স্বেচ্ছাসেবক নির্ভুলতায় প্রচার করে। আরও কিছুক্ষণ সময় নিতে পারি।
Dawg

3
যে কোনও সিস্টেমে পাইথন এ ক্ষেত্রে কাজ করবে, যেহেতু পাইথন প্রয়োজনে স্বয়ংক্রিয়ভাবে দীর্ঘ পূর্ণসংখ্যায় চলে যায়। এবং যদি এটি পর্যাপ্ত না হয় তবে এটি বড় সংখ্যায়ও চলে যাবে।
অলোক সিংহল

12
@ 0x499602D2: এটি ধরণের কঠোর। ওপি নিজেই এটিকে ভোট দিয়েছিল। তিনি বিশেষত জিজ্ঞাসা করেছিলেন পাইথনের ক্ষেত্রেও কি এ জাতীয় সমস্যা ছিল? উত্তর, না এটা না। কোডটি এটি দেখানোর জন্য নয়। WTH?
Dawg

10
পাইথনের উদাহরণটি অত্যধিক দীর্ঘ, কেবল যোগফলটি ব্যবহার করুন (এক্সরেঞ্জ (ইনট (1e9) +1)) (.... যোগফল পুনরাবৃত্তিতে কাজ করে)
জেসন মরগান

101

আপনার গো কোডটি সঠিক উত্তর দেওয়ার জন্য পর্যাপ্ত বিট সহ পূর্ণসংখ্যার গাণিতিক ব্যবহার করে। পিএইচপি বা নোড.জেএস কখনই স্পর্শ করেনি, তবে ফলাফল থেকে আমি সন্দেহ করি যে গণিতটি ভাসমান পয়েন্ট সংখ্যা ব্যবহার করে করা হয়েছে এবং সুতরাং এই মাত্রার সংখ্যার জন্য সঠিক না হওয়ার আশা করা উচিত।


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
এবং নোডজেএসে (এবং সাধারণভাবে জাভাস্ক্রিপ্ট) সমস্ত পাটিগণিত ক্রিয়াকলাপ (বিট অপারেশন ব্যতীত) এমন আচরণ করে যেন সেগুলি ভাসমান পয়েন্ট সংখ্যাগুলি দ্বারা সম্পন্ন হয়েছিল। তারা প্রকৃতপক্ষে ব্যক্তিগত জাভাস্ক্রিপ্ট ইঞ্জিনগুলির সিদ্ধান্তের আওতাধীন হুড পার্থক্য কিনা তা নয়।
পিটার ওলসন

13
জাভাস্ক্রিপ্টের নির্দিষ্টকরণে কোনও পূর্ণসংখ্যার প্রকার নেই। সমস্ত সংখ্যা ভাসমান পয়েন্ট।
toasted_flakes

8
@grasGendarme আছে ES5 স্পেস বিভিন্ন সংখ্যক রূপান্তর এবং ম্যান্ডেটগুলি নির্দিষ্ট করে যা তাদের বিটওয়াইফ শিফটে ডাকা হয় , উদাহরণস্বরূপ। পর্দার আড়ালে বলতে হবে, জাভাস্ক্রিপ্টে পূর্ণসংখ্যার প্রকারগুলি ব্যবহৃত হয়, তবে সমস্ত গাণিতিক অপারেটরগুলি তাদের সাথে কিছু করার আগে তাদের অপারেশনগুলিকে ভাসমান পয়েন্ট সংখ্যায় রূপান্তর করে (সংকলক অপ্টিমাইজেশন বাদ দিয়ে)।
পিটার ওলসন

2
এখানে কোডটি অনুমেয় হয়ে গেছে বলে আমি অনুমান করেছি কারণ আমি ভাসা 64৪ ব্যবহার করেছি এবং না int৪ টি ব্যবহার করেছি .. কেবলমাত্র নিশ্চিত করেছেন যে এটির 32 বা 64 বিটের কোনও যোগসূত্র নেই
বাবা

45

কারণটি হল আপনার পূর্ণসংখ্যের ভেরিয়েবলের sumমান সর্বাধিক মানকে ছাড়িয়ে যায়। এবং sumআপনি যেটি পেয়ে যাবেন এটি ফ্লোট-পয়েন্ট পাটিগণিতের ফলাফল যা গোলটি বন্ধ করে জড়িত। যেহেতু অন্যান্য উত্তরগুলি সঠিক সীমাটি উল্লেখ করে না, তাই আমি এটি পোস্ট করার সিদ্ধান্ত নিয়েছি।

পিএইচপি-র জন্য সর্বোচ্চ পূর্ণসংখ্যার মান:

  • 32-বিট সংস্করণটি 2147483647
  • 64-বিট সংস্করণটি 9223372036854775807

সুতরাং এর অর্থ হয় আপনি 32 বিট সিপিইউ বা 32 বিট ওএস বা 32 বিট সংযুক্ত সংস্করণ পিএইচপি ব্যবহার করছেন। এটি ব্যবহার করে পাওয়া যাবে PHP_INT_MAXsumসঠিকভাবে গণনা করা হবে যদি আপনি একটি 64 বিট মেশিনে এটা করতে।

জাভাস্ক্রিপ্টে সর্বোচ্চ পূর্ণসংখ্যার মান 9007199254740992 । আপনার সাথে কাজ করতে পারেন সবচেয়ে বড় সঠিক অবৈধ মান হ'ল 2 53 (এই প্রশ্ন থেকে নেওয়া )। sumএই সীমা ছাড়িয়ে গেছে।

যদি পূর্ণসংখ্যার মানটি এই সীমা ছাড়িয়ে যায় না, তবে আপনি ভাল। অন্যথায় আপনাকে স্বেচ্ছাচারিত নির্ভুলতা পূর্ণসংখ্যার লাইব্রেরিটি সন্ধান করতে হবে।


28

সিটিতে উত্তরটি এখানে রয়েছে, সম্পূর্ণতার জন্য:

#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;
}

এই ক্ষেত্রে কীটি সি 99 এর long long ডেটা টাইপ ব্যবহার করছে । এটা তোলে সবচেয়ে বড় আদিম স্টোরেজ সি পরিচালনা করতে পারেন উপলব্ধ করা হয় এবং এটি সত্যিই চালায়, সত্যিই দ্রুত। এই long longটাইপটি বেশিরভাগ 32 বা 64-বিট মেশিনেও কাজ করবে।

একটি সতর্কতা রয়েছে: মাইক্রোসফ্ট দ্বারা সরবরাহিত সংকলকগণ 14 বছরের পুরানো সি 99 স্ট্যান্ডার্ডকে স্পষ্টভাবে সমর্থন করে না, সুতরাং ভিজ্যুয়াল স্টুডিওতে এটি চালানো একটি ক্র্যাপশট।


3
এমএসভিসি ++ একটি সি ++ সংকলক, এবং সি ++ long longসি ++ 11 স্ট্যান্ডার্ডে পেয়েছে । যদিও এটি কয়েক বছরের জন্য একটি এমএসভিসি ++ এবং জি ++ এক্সটেনশন হয়েছে।
এমএসএলটারগুলি

1
@ এসএমএলটারগণ সুতরাং একটি সি ++ বৈশিষ্ট্য হওয়ায় এটি কোনও স্ট্রেট সি প্রোগ্রাম সংকলনকারীকে সত্যিই সহায়তা করবে না। আমি কখনই সি থেকে সি ++ এ স্যুইচ করার চেষ্টা করিনি, তাই আমি জানি না যে সেই কর্মক্ষেত্রটি আসলে কাজ করবে কিনা।
সাইবারস্কুল

19
এবং সুন্দরভাবে, জিসিসি বা অনুকূলকরণের সাথে movabsq $500000000500000000, %rsi
কলং

3
শুধু gcc -O3বা clang -O3। নির্দিষ্ট অপ্টিমাইজেশনের নাম আমি জানি না। মূলত সংকলকটি লক্ষ্য করে যে লুপটির ফলাফল কোনও যুক্তির উপর নির্ভর করে না এবং সংকলনের সময় এটি গণনা করে।
টোর ক্লিংবার্গ

1
সি 99 দীর্ঘ দীর্ঘতমের ন্যূনতম আকার 64 বিট রয়েছে এবং যতদূর আমি জানি 32-বিট এবং 64-বিট উভয় প্ল্যাটফর্মে 64 বিট। কোয়াড বা অক্ট ইনটসের জন্য আমি সাধারণ সমর্থন দেখিনি।
ডেভিন লেন

21

আমার অনুমান যে যখন যোগফলটি একটি নেটিভের int(2 31 -1 = 2,147,483,647) সক্ষমতা ছাড়িয়ে যায় , নোড.জেএস এবং পিএইচপি একটি ভাসমান পয়েন্ট উপস্থাপনায় চলে যায় এবং আপনি রাউন্ড-অফ ত্রুটি পেতে শুরু করেন। গো এর মতো একটি ভাষা সম্ভবত যতক্ষণ সম্ভব পূর্ণসংখ্যা ফর্মের সাথে (যেমন, -৪-বিট পূর্ণসংখ্যার) আটকে থাকার চেষ্টা করবে (যদি সত্যিকার অর্থে এটি এর সাথে শুরু না হয়)। যেহেতু উত্তরটি একটি 64-বিট পূর্ণসংখ্যায় ফিট করে, সুতরাং গণনাটি হুবহু।


নোড.জেএস স্পষ্টভাবে কোন প্রকার টাইপ নেই। এটি একটি ফ্লোট টাইপের কাজ করছে।
গ্রেফ্যাড

@ গ্রেফ্যাড - হ্যাঁ, আমি অনুমান করি যে এটি সমস্ত এক্সমা স্ক্রিপ্ট-অনুবর্তী পরিবেশের ক্ষেত্রে সত্য।
টেড হপ

এটি কি (2 ** 31 - 1) নয়?
জাচারি হান্টার

@ জাচারি হান্টার - সত্যই তা। ত্রুটিটি ধরার জন্য ধন্যবাদ
টেড হপ

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 এ on
Qtax

7
আপনার যদি সত্যিই বড় সংখ্যার প্রয়োজন হয় তবে, bignumবা ব্যবহার করুন bigint। উভয়ই মূল মডিউল, অর্থাৎ তারা পার্ল v5.8.0 বা ততোধিক সংস্করণ দিয়ে ইনস্টল are দেখুন http://perldoc.perl.org/bignum.htmlএবংhttp://perldoc.perl.org/bigint.html
shawnhcorey

আমি এটি একটি 32-বিট পিপিসি ম্যাকের মধ্যে চলমান পার্ল 5.12.4 এ চালিয়ে 50000000000500000000 পেয়েছি
সাইবারস্কুল

17

এর উত্তর "আশ্চর্যজনকভাবে" সহজ:

প্রথম - আপনার বেশিরভাগ হিসাবে জানা থাকতে পারে - একটি 32-বিট পূর্ণসংখ্যা −2,147,483,648 থেকে শুরু করে 2,147,483,647 । সুতরাং, পিএইচপি কোনও ফলাফল পেলে কি হয়, এটি এর চেয়ে আরও বড়?

সাধারণত, কেউ তাত্ক্ষণিক "ওভারফ্লো" আশা করতে পারে, যার ফলে 2,147,483,647 + 1 −2,147,483,648 এ পরিণত হয় । যাই হোক, এটা ব্যপার না. যদি পিএইচপি কোনও বৃহত সংখ্যার মুখোমুখি হয় তবে এটি INT এর পরিবর্তে ফ্ল্যাট ফিরিয়ে দেয়।

পিএইচপি যদি পূর্ণসংখ্যার প্রান্তের সীমা ছাড়িয়ে কোনও সংখ্যার মুখোমুখি হয়, তবে এটি পরিবর্তে একটি ফ্লোট হিসাবে ব্যাখ্যা করা হবে। এছাড়াও, কোনও ক্রিয়াকলাপের ফলে সংখ্যার পূর্ণসংখ্যার প্রান্তের সীমানা ছাড়িয়ে যাওয়ার ফলাফল পরিবর্তে একটি ফ্লোট ফিরে আসবে।

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

এটি বলেছে এবং পিএইচপি ফ্লাট বাস্তবায়ন আইইইই 754 ডাবল স্পষ্টতা ফর্ম্যাট অনুসরণ করছে, এর অর্থ এই যে পিএইচপি নির্ভুলতা ছাড়াই 52 বিট পর্যন্ত সংখ্যার সাথে ডিল করতে সক্ষম হয়। (একটি 32-বিট সিস্টেমে)

সুতরাং, সেই বিন্দুতে, যেখানে আপনার যোগফল 9,007,199,254,740,992 (যা 2 ^ 53 ) হিট করেছে পিএইচপি গণিতে ফিরিয়ে দেওয়া ফ্লোট মানটি আর যথেষ্ট পরিমাণে সুনির্দিষ্ট হবে না।

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

এই উদাহরণটি পয়েন্টটি দেখায়, যেখানে পিএইচপি নির্ভুলতা হারাচ্ছে। প্রথম, সর্বশেষ হিট বিট বাদ দেওয়া হবে, যার ফলে প্রথম 2 টি এক্সপ্রেশন একটি সমান সংখ্যার ফলস্বরূপ হয় - যা তারা নয় n't

এখন থেকে, ডিফল্ট ডেটা-টাইপের সাথে কাজ করার সময় পুরো গণিতটি ভুল হয়ে যাবে।

Other পাইথন বা পার্লের মতো অন্যান্য ব্যাখ্যাযুক্ত ভাষার ক্ষেত্রেও কি একই সমস্যা?

আমি তাই মনে করি না. আমি মনে করি এটি এমন একটি ভাষার সমস্যা যার কোনও ধরণের সুরক্ষা নেই। উপরে উল্লিখিত ইন্টিজার ওভারফ্লো যখন স্থির ডেটা ব্যবহার করে এমন প্রতিটি ভাষায় ঘটবে, তবে টাইপ-সুরক্ষা ছাড়াই থাকা ভাষাগুলি অন্য ডেটাটাইপগুলির সাথে এটি ধরার চেষ্টা করতে পারে। যাইহোক, একবার তাদের "প্রাকৃতিক" (সিস্টেম-প্রদত্ত) বর্ডারে আঘাত করলে তারা কিছু দিতে পারে তবে সঠিক ফলাফল।

যাইহোক, প্রতিটি ভাষার এই ধরণের দৃশ্যের জন্য আলাদা আলাদা থ্রেডিং থাকতে পারে।


15

অন্যান্য উত্তরগুলি ইতিমধ্যে এখানে কী ঘটছে তা ব্যাখ্যা করেছে (যথারীতি ভাসমান পয়েন্ট যথার্থ)।

একটি সমাধান হ'ল যথেষ্ট পরিমাণে পূর্ণসংখ্যা টাইপ ব্যবহার করা, বা আশা করা প্রয়োজন ভাষা যদি একটি চয়ন করে one

অন্য সমাধানটি হ'ল সামিট অ্যালগরিদম ব্যবহার করা যা নির্ভুলতার সমস্যা সম্পর্কে জানে এবং তার চারপাশে কাজ করে। নীচে আপনি একই সমষ্টিটি খুঁজে পান প্রথমে bit৪ বিট পূর্ণসংখ্যার সাথে, তারপরে bit৪ বিট ভাসমান বিন্দু এবং তারপরে আবার ভাসমান বিন্দু ব্যবহার করে তবে কাহান সংক্ষেপণ অ্যালগরিদম দিয়ে

সি # তে লিখিত, তবে অন্যান্য ভাষার ক্ষেত্রেও এটি একইরকম।

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

কাহান সমষ্টি একটি সুন্দর ফলাফল দেয়। এটি গণনা করতে অবশ্যই অনেক বেশি সময় নেয়। আপনি এটি ব্যবহার করতে চান কিনা ক) আপনার পারফরম্যান্স বনাম যথাযথ প্রয়োজনগুলির উপর নির্ভর করে এবং খ) আপনার ভাষা কীভাবে বনাম পূর্ণমানের বনাম ভাসমান পয়েন্টের ডেটা টাইপ পরিচালনা করে।


@ বাবা এটি ওপিতে নোড.জেএস / জাভাস্ক্রিপ্টের মতোই। কেন 500000000067109000 বনাম 500000000067108992… কোনও ধারণা নেই।
লিনাক

সম্ভবত বাবা হাজার হাজার বিভাজকের জন্য বিন্দু ব্যবহারে আগ্রহী: ইংরেজি সাধারণত কমাগুলি প্রত্যাশা করে। আপনি আরও নিরপেক্ষ গড় হিসাবে আন্ডারস্কোরগুলিও ব্যবহার করতে পারেন।
didierc

14

আপনার যদি 32-বিট পিএইচপি থাকে, আপনি এটি বিসি দিয়ে গণনা করতে পারেন :

<?php

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

জাভাস্ক্রিপ্টে আপনাকে স্বেচ্ছাসেবী সংখ্যা লাইব্রেরি ব্যবহার করতে হবে, উদাহরণস্বরূপ বিগইন্টিজার :

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তবে আমার ২.6 গিগাহার্টজ ইন্টেল আই on এর জন্য 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)। ইনজেক্ট (: +)
ম্যাগনাস

@ ম্যাগনুস: আমি যা ভেবেছিলাম তা আমি প্রথমে চেষ্টা করেছি, তবে এটি একটি বিশাল স্মৃতি ফাঁসির কারণ হয়ে দাঁড়িয়েছে। আপনার কাজ করা মনে হচ্ছে ...
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৪-বিটের চেয়ে বেশি সংখ্যায় প্রবেশ করেন তবে এটি হুডের নীচে লিবিগ্যাম্প ব্যবহার করে, এটি সেখানে দ্রুত নির্বিচারে নির্ভুলতা গ্রন্থাগারগুলির মধ্যে একটি।


4

যুবা যুগে যুগে যুগে সময় নিয়েছে, তবে সঠিক উত্তর দেয়:

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

4

পিএইচপি-তে সঠিক ফলাফল পেতে আমার মনে হয় আপনার বিসি ম্যাথ অপারেটরগুলি ব্যবহার করা দরকার: http://php.net/manual/en/ref.bc.php

স্কালায় সঠিক উত্তর এখানে। আপনাকে লংস ব্যবহার করতে হবে অন্যথায় আপনি সংখ্যাটি উপচে ফেলেছেন:

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)

এন = 1e9 এর জন্য: আউটপুট = এন / 2 * (এন + 1)

এটি সেই সমস্ত ডেটা লুপিংয়ের চেয়ে অনেক দ্রুত। আপনার প্রসেসর এটির জন্য আপনাকে ধন্যবাদ জানাবে। এবং এখানে এই খুব সমস্যা সম্পর্কিত একটি আকর্ষণীয় গল্প:

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


11
আপনি কি মনে করেন যে ক্যালিনিনগ্রাদের প্রেগেল জুড়ে প্রতিটি ব্রিজ পেরিয়ে দু'বার কোনও ব্রিজ পার না করেই চলতে পারে? অনেক লোক চেষ্টা করেছে এবং ব্যর্থ হয়েছে, কিন্তু কেউই এখনও এটি প্রতিষ্ঠা করতে পারেনি যে এটি অসম্ভব। এটি চ্যালেঞ্জের মতো বলে মনে হচ্ছে আপনি সমাধানের জন্য অনন্যভাবে যোগ্য হয়ে উঠবেন।
jwg

3

এটি পূর্ণসংখ্যা কাস্ট জোর করে পিএইচপি-তে যথাযথ ফলাফল দেয়।

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

3

কমন লিস্প হ'ল দ্রুততম ব্যাখ্যিত * ভাষাগুলির মধ্যে একটি এবং নির্বিচারে বড় ইন্টিজারগুলি ডিফল্টরূপে সঠিকভাবে পরিচালনা করে। এটি এসবিসিএল এর সাথে প্রায় 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
  • ব্যাখ্যার মাধ্যমে, আমার অর্থ, আমি এই কোডটি আরপিএল থেকে চালিয়েছি, এসবিসিএল এটি দ্রুত চালিত করার জন্য অভ্যন্তরীণভাবে কিছু জেআইটিিং করেছে, তবে তত্ক্ষণাত চলমান কোডটির গতিশীল অভিজ্ঞতা একই।

(সময় হিসাবে (1 থেকে 1000000000 যোগফল x পর্যন্ত লুপ)) হিসাবে সরলীকৃত করা যেতে পারে। আমি ডিক্লোরেশন যুক্ত করে ~ 5x গতি পেয়েছি: (সময় (স্থানীয়ভাবে (ঘোষণা (অপ্টিমাইজ (গতি 3)) (সুরক্ষা 0))) (1 ধরণের ফিকনামের জন্য লুপ 1 থেকে 1000000000 আই-টাইপ ফিকনাম)))
হুয়াইয়ান

এটি ভ্রান্ত। আপনি অন্য ভাষায় অন্ধ হয়ে যাবেন না! লিসপে এটিকে লেখার সঠিক উপায় হ'ল: (1-থেকে-n-n (n) (/ (* n (1+ n)) 2)) সময় (যোগফল 1-থেকে-এন পর্যন্ত) 1000000000)) চালাতে 14 টি মাইক্রোসেকেন্ড (0.000014 সেকেন্ড) নিয়েছিল। সেই সময়কালে এবং 4 টি উপলব্ধ সিপিইউ কোর সহ 0 টি মাইক্রোসেকেন্ড (0.000000 সেকেন্ড) ব্যবহারকারী মোডে 0 মাইক্রোসেকেন্ড (0.000000 সেকেন্ড) ব্যয় করা হয়েছিল সিস্টেম মোডে -> 50000000050000000000
তথ্য

@ ইনফর্মটিমাগো: এটি ভুল নয়। আমি প্রশ্নের অপরিহার্য লুপ স্টাইলটি অনুলিপি করছিলাম এবং অনেকেই উল্লেখ করেছেন যে প্রশ্নটি নিজেই উল্লেখ করেছে যে গণনার সহজ উপায় আছে is Chillax।
পোস্টফিউচারিস্ট

3

@ পোস্টফিউচারিস্টের কমন লিস্প উত্তরে মন্তব্য করার মতো যথেষ্ট খ্যাতি আমার নেই, তবে এটি আমার মেশিনে এসবিসিএল ১.১.৮ সহ ms 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

র‌্যাকেট ভি 5.3.4 (এমবিপি; এমএসে সময়):

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

1
আমার উত্তরটি মুছে ফেলা হয়েছে আপনার 6 মিনিটের পরে, আমি একবার আপনার লক্ষ্য করেছি। :)
গ্রেগ হেন্ডারশট

3

রেবলে ভাল কাজ করে:

>> sum: 0
== 0

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

>> type? sum
== integer!

এটি রিবোল 3 ব্যবহার করছিল যা 32 বিট সংকলিত হওয়া সত্ত্বেও এটি 64-বিট পূর্ণসংখ্যা ব্যবহার করে (রিবোল 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

অ্যাক্টিভ পার্ল v5.10.1 32 বিট উইন্ডোতে, ইন্টেল কোর 2duo 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
যদি ফলাফলটি সরবরাহ করে তবেই কেবলমাত্র bit MY_FAVOURITE_LANGUAGE জবাবগুলির একমাত্র ক্ষুদ্র বিটটি হ'ল
jwg

@jwg হ্যাঁ দুঃখিত আমি লাইনের শেষটি - মিসড আপডেটটি মিস করেছি।
কৃষ্ণাঙ্গ

3

awk:

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

পিএইচপি হিসাবে একই ভুল ফলাফল উত্পাদন করে:

500000000067108992

দেখে মনে হচ্ছে যে সংখ্যাগুলি সত্যই বড় হলে এডব্লু কে ভাসমান পয়েন্ট ব্যবহার করে, তাই কমপক্ষে উত্তরটি সঠিক-ক্রম-মাত্রার is

টেস্ট রান:

$ 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 জীবনের শেষ)।

যদি টিসিএল 8.5 বা নতুনতর ব্যবহার করে যা নির্বিচারে বড় পূর্ণসংখ্যা থাকে তবে এটি সঠিক ফলাফল প্রদর্শন করবে।

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

বাইট-সংকলন করার জন্য আমি একটি পরীক্ষার ভিতরে পরীক্ষা রেখেছিলাম।


2

পিএইচপি কোডের জন্য উত্তরটি এখানে রয়েছে :

একটি পূর্ণসংখ্যার আকার প্ল্যাটফর্ম নির্ভর, যদিও সর্বাধিক প্রায় দুই বিলিয়ন মূল্য স্বাভাবিক মান (এটি 32 বিট স্বাক্ষরিত)। -৪-বিট প্ল্যাটফর্মগুলির সাধারণত সর্বাধিক মান 9E18 থাকে। পিএইচপি স্বাক্ষরবিহীন পূর্ণসংখ্যার সমর্থন করে না। ধ্রুবক PHP_INT_SIZE এবং পিএইচপি ৪.৪.০ এবং পিএইচপি ৫.০.৫ থেকে ধ্রুবক পিএইচপিএনপিএএমএএমএক্স ব্যবহার করে সর্বাধিক মান ব্যবহার করে পূর্ণসংখ্যার আকার নির্ধারণ করা যায়।


2

হারবার:

proc Main()

   local sum := 0, i

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

   ? sum

   return

ফলাফল 500000000500000000। (উভয় উইন্ডোজ / মিংডাব্লু / x86 এবং ওএসএক্স / ঝনঝন / এক্স 64)


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> অকেজো: থেকে_সাম (1,1000000000)। 500000000500000000


2

মজার বিষয়, পিএইচপি 5.5.1 499999999900000000 (30 ডলারে) দেয়, যখন ডার্ট 2 জে 500000000067109000 দেয় (যা প্রত্যাশিত, যেহেতু এটি জেএস কার্যকর করা হয়)। সি এল এল ডার্ট তাত্ক্ষণিকভাবে সঠিক উত্তর দেয়।


2

এরলং প্রত্যাশিত ফলাফলও দেয়।

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.