Yorumlanan diller üzerinde çok büyük tamsayılarla çalışırken beklenmedik sonuçlar


192

Toplamını almaya çalışıyorum 1 + 2 + ... + 1000000000, ancak PHP ve Node.js komik sonuçlar alıyorum .

PHP

$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

Doğru cevap kullanılarak hesaplanabilir

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

Doğru cevap = 500000000500000000 , bu yüzden başka bir dil denemeye karar verdim.

GİT

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

Ama iyi çalışıyor! Peki PHP ve Node.js kodumda sorun nedir?

Belki de bu, yorumlanmış diller sorunudur ve bu yüzden Go gibi derlenmiş bir dilde çalışır. Eğer öyleyse, Python ve Perl gibi diğer yorumlanmış diller de aynı sorunla karşılaşır mı?


36
buna ihtiyacınız var: php.net/manual/tr/book.bc.php , yoksa başka bir şey cehennem dolana kadar başınızı IEEE 754'e karşı bastıracaktır .
tereško

5
PHP'de (örn. 64 bit) büyük sayıları işlemek için GMP işlevlerini kullanın, bu durumda gmp_add ().
Jeffrey

113
Süper verimlilik için, döngüleriniz gerçekten 0 yerine 1'den başlamalıdır.: P
Graham Borland

55
toplam (1'den N'ye) = (N / 2) * (N + 1)
Phong

5
@Baba 0, hesaplamalarınız için gereksizdir, bu nedenle 0'dan 0'a eklemek için fazladan bir döngü yinelemesine gerek yoktur
Brian Warshaw

Yanıtlar:


155

Python çalışır:

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

Veya:

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

Python'un intotomatik longözelliği, keyfi hassasiyeti destekleyen bir Python'a yükselir. 32 veya 64 bit platformlarda doğru cevabı verecektir.

Bu, platformun bit genişliğinden çok daha büyük bir güce 2 yükseltilerek görülebilir:

>>> 2**99
633825300114114700748351602688L

(Python ile), PHP'de aldığınız hatalı değerlerin, değerler 2 ** 32-1'den büyük olduğunda PHP'nin bir kayan noktaya yükseltilmesinden kaynaklandığını gösterebilirsiniz:

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

Bunu 32 veya 64 bit sistemde mi çalıştırdınız?
Baba

4
Python ints otomatik olarak taşma yerine rastgele hassasiyete geçtiği için ne olursa olsun (32 bit 64 bit) çalışmalıdır. Tho biraz daha uzun sürebilir.
dawg

3
Herhangi bir sistemdeki Python bu durumda çalışacaktır, çünkü Python gerekirse otomatik olarak uzun tamsayılara geçer. Ve eğer bu yeterli değilse, büyük tamsayılara da geçecektir.
Alok Singhal

12
@ 0x499602D2: Bu biraz sert. OP kendisi oy verdi. Özellikle bunun Python'da benzer bir sorun olup olmadığını sordu. Cevap, hayır değil. Olmadığını göstermek için kod. WTH?
dawg

10
Python örneği aşırı uzun, sadece sum (xrange (int (1e9) +1)) kullanın (.... sum yinelemelerde çalışır)
Jason Morgan

101

Go kodunuz, tam bir cevap vermek için yeterli bit içeren tamsayı aritmetiği kullanır. PHP veya Node.js'ye hiç dokunmadım, ancak sonuçlardan matematiğin kayan nokta sayıları kullanılarak yapıldığından ve bu büyüklükteki rakamlar için tam olmamasından şüpheleniyorum .


46
Evet. 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
Ve NodeJS'de (ve genel olarak JavaScript'te) tüm aritmetik işlemler (bit işlemleri hariç) kayan nokta sayılarıyla yapılmış gibi davranırlar. Aslında olup olmadıkları, her bir JavaScript motorunun kararlarına tabi olan temel bir ayrımdır.
Peter Olson

13
Javascript belirtiminde tamsayı türü yoktur. Tüm sayılar kayan noktalardır.
toasted_flakes

8
@grasGendarme Var. ES5 spesifikasyonu , örneğin bitsel kaydırmalarda çağrılmaları için çeşitli tamsayı dönüşümlerini ve zorunluluklarını belirtir . Yani perde arkasında, Javascript'te tamsayı türleri kullanılır, ancak tüm aritmetik işleçler, onlarla herhangi bir şey yapmadan önce işlenenlerini kayan nokta sayılarına dönüştürür (kısıtlayıcı derleme optimizasyonları).
Peter Olson

2
İşte ben onun float64 ve int64 değil kullanılan çünkü berbat sanırım kodu .. Sadece 32 veya 64 bit ile ilgisi yoktur
Baba

45

Bunun nedeni, tamsayı değişkeninizin sumdeğerinin maksimum değeri aşmasıdır. Ve sumelde ettiğiniz yuvarlanma içeren kayan nokta aritmetiğinin sonucudur. Diğer cevaplar kesin sınırlardan bahsetmediğinden, göndermeye karar verdim.

PHP için maksimum tamsayı değeri:

  • 32 bit sürüm 2147483647'dir
  • 64-bit sürüm 9223372036854775807

Yani 32 bit CPU veya 32 bit işletim sistemi ya da PHP'nin 32 bit derlenmiş sürümünü kullandığınız anlamına gelir. Kullanılarak bulunabilir PHP_INT_MAX. sumEğer 64 bit makinede yaparsanız doğru hesaplanacaktır olacaktır.

JavaScript'teki maksimum tam sayı değeri 9007199254740992'dir . Çalışabileceğiniz en büyük tam integral değeri 2 53'tür (bu sorudan alınmıştır ). sumBu sınırı aşmaktadır.

Tamsayı değeri bu sınırları aşmazsa, iyisinizdir. Aksi takdirde, hassas tamsayı tamsayı kütüphanelerini aramanız gerekir.


28

İşte tamlık için C'deki cevap:

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

Bu durumda anahtar, C99'un long long veri türünü kullanmaktır. C'nin yönetebileceği en büyük ilkel depolamayı sağlar ve gerçekten çok hızlı çalışır . long longTipi aynı zamanda en herhangi 32 veya 64 bit makinede çalışacak.

Bir uyarı var: Microsoft tarafından sağlanan derleyiciler 14 yaşındaki C99 standardını açıkça desteklemiyor, bu nedenle Visual Studio'da çalıştırmak için bir crapshot.


3
MSVC ++ bir C ++ derleyicisidir ve C ++ long longC ++ 11 standardına sahiptir. Birkaç yıldır bir MSVC ++ ve g ++ uzantısı oldu.
MSalters

1
@MSalters Bu yüzden bir C ++ özelliği olarak kimsenin düz bir C programı derlemesine yardımcı olmaz. Asla C + C ++ geçiş denedim, bu yüzden bu geçici çözüm gerçekten işe yarayacak mı bilmiyorum.
CyberSkull

19
Ve güzel, optimizasyonlu GCC veya Clang tüm döngüyü dönüştürüyormovabsq $500000000500000000, %rsi
Tor Klingberg

3
Sadece gcc -O3ya da clang -O3. Belirli optimizasyonun adını bilmiyorum. Temel olarak derleyici, döngünün sonucunun herhangi bir bağımsız değişkene bağlı olmadığını fark eder ve derleme zamanında hesaplar.
Tor Klingberg

1
C99 uzunluğunda en az 64 bit boyutu vardır ve bildiğim kadarıyla hem 32 bit hem de 64 bit platformlarda 64 bittir. Dörtlü veya sekizli girişler için genel destek görmedim.
Devin Lane

21

Benim tahminim, toplam yerel bir kapasiteyi aştığında int(2 31 -1 = 2.147.483.647), Node.js ve PHP'nin bir kayan nokta gösterimine geçmesi ve yuvarlama hataları almaya başlamanızdır. Go gibi bir dil muhtemelen olabildiğince uzun bir tamsayı formuyla (örneğin, 64 bit tamsayılar) yapışmaya çalışacaktır (eğer gerçekten bununla başlamadıysa). Cevap 64 bitlik bir tamsayıya sığdığı için hesaplama kesindir.


Node.js'nin açıkça bir int türü yoktur. Şamandıra tipinde çalışıyor.
greyfade

@greyfade - Evet, sanırım bu tüm EcmaScript uyumlu ortamlar için geçerli.
Ted Hopp

Öyle değil mi (2 ** 31-1)?
Zachary Hunter

@ZacharyHunter - Gerçekten de öyle. Bu hatayı yakaladığınız için teşekkür ederiz.
Ted Hopp

19

Perl betiği bize beklenen sonucu verir:

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
Bunu 32 veya 64 bit sistemde mi çalıştırdınız?
Baba

2
64 bit sistemde idam edildi
Miguel Prz

3
4.99999999067109e+017Perl v5.16.1 MSWin32-x86.
Qtax

7
Gerçekten büyük sayılara ihtiyacınız varsa bignumveya tuşunu kullanın bigint. Her ikisi de çekirdek modüllerdir, yani Perl v5.8.0 veya daha üstü ile kurulurlar. Bakınız http://perldoc.perl.org/bignum.htmlvehttp://perldoc.perl.org/bigint.html
shawnhcorey

Perl 5.12.4 çalıştıran 32 bit PPC Mac üzerinde çalışan 500000000500000000 aldım.
CyberSkull

17

Bunun cevabı "şaşırtıcı bir şekilde" basit:

İlk - çoğunuz bildiğiniz gibi - dan aralıkları tamsayı 32 bit -2,147,483,648 için 2,147,483,647 . Peki, PHP bir sonuç alırsa, bundan daha LARGER olur?

Genellikle, 2.147.483.647 + 1'in −2.147.483.648'e dönüşmesine neden olan hemen bir "Taşma" beklenir . Ancak, durum böyle değil. PHP daha büyük bir sayıyla karşılaşırsa, INT yerine FLOAT döndürür.

PHP, tamsayı türünün sınırlarının ötesinde bir sayıyla karşılaşırsa, bunun yerine kayan sayı olarak yorumlanır. Ayrıca, tamsayı tipinin sınırlarının ötesinde bir sayı ile sonuçlanan bir işlem, bunun yerine bir kayan nokta döndürür.

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

Bununla birlikte, PHP FLOAT uygulamasının IEEE 754 çift kesinlikli Format'ı izlediğini bilmek, PHP'nin hassasiyeti kaybetmeden 52 bit'e kadar sayılarla başa çıkabileceği anlamına gelir. (32 bit Sistemde)

Böylece, Sum'ınızın 9,007,199,254,740,992'ye ( 2 ^ 53 ) çarptığı noktada , PHP Maths tarafından döndürülen Float değeri artık yeterince hassas olmayacaktır.

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

Bu örnek PHP'nin kesinliğini yitirdiği Noktayı gösterir. İlk olarak, son anlamlı bit atılacak ve ilk 2 ifadenin eşit sayı ile sonuçlanmasına neden olacak - ki bunlar değil.

ŞİMDİ AÇIK'tan itibaren, varsayılan veri türleriyle çalışırken tüm matematik yanlış olacaktır.

• Python veya Perl gibi yorumlanmış diğer diller için de aynı sorun var mı?

Ben öyle düşünmüyorum. Bence bu, tür güvenliği olmayan bir dil sorunu. Yukarıda belirtildiği gibi bir Tamsayı Taşması sabit veri türlerini kullanan her dilde OLACAKTIR, tip güvenliği olmayan diller bunu diğer veri türleriyle yakalamaya çalışabilir. Bununla birlikte, "doğal" (Sistem tarafından verilen) Sınırlarına ulaştıklarında - her şeyi döndürebilirler, ancak doğru sonuç.

Ancak, her dilin böyle bir Senaryo için farklı konuları olabilir.


15

Diğer cevaplar burada ne olduğunu zaten açıkladı (her zamanki gibi kayan nokta hassasiyeti).

Bir çözüm, yeterince büyük bir tamsayı türü kullanmak veya dilin gerekirse bir tane seçeceğini ummaktır.

Diğer çözüm, hassaslık sorununu bilen ve bu sorunu gideren bir toplama algoritması kullanmaktır. Aşağıda aynı toplamı, önce 64 bit tamsayı ile, sonra 64 bit kayan nokta ile ve sonra tekrar kayan nokta kullanarak, ancak Kahan toplama algoritması ile bulacaksınız .

C # ile yazılmış, ancak aynı diğer diller için de geçerlidir.

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

Kahan toplamı güzel bir sonuç verir. Elbette hesaplanması çok daha uzun sürüyor. Kullanmak isteyip istemediğiniz, a) performansınızla hassasiyet gereksinimlerinize ve b) dilinizin tamsayı ile kayan nokta veri türlerini nasıl ele aldığına bağlıdır.


@Baba OP'deki Node.js / JavaScript ile aynı. Neden 500000000067109000'e karşı 500000000067108992… hiçbir fikrim yok.
linac

Belki Baba bin ayırıcı için nokta kullanımı ile ilgilenir: İngilizce genellikle virgül bekler. Alt çizgileri daha tarafsız bir ortalama olarak da kullanabilirsiniz.
didierc

14

32-Bit PHP'niz varsa, bc ile hesaplayabilirsiniz :

<?php

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

Javascript'te isteğe bağlı sayı kitaplığı kullanmanız gerekir, örneğin BigInteger :

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

Go ve Java gibi dillerde bile sonunda rasgele sayı kitaplığı kullanmak zorunda kalacaksınız, sayınız 64 bit için yeterince küçük, 32 bit için çok yüksek oldu.


12

Ruby'de:

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

5000000005000000002,6 GHz Intel i7 cihazımda yazdırır , ancak 4 dakika sürer.


Magnuss ve Jaunty'nin çok daha fazla Ruby çözümü var:

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

Bir karşılaştırma ölçütü çalıştırmak için:

$ 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). Enjekte (: +)
Magnuss

@Magnuss: İlk başta denediğimi sanıyordum, ama büyük bir bellek sızıntısına neden oldu. Sevgiler işe yarıyor ...
cgenco

11

Büyük tamsayılar için node-bigint kullanıyorum:
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);

Bu kesin test için yerel 64 bitlik şeyler kullanabilen bir şey kadar hızlı değildir, ancak 64 bit'ten daha büyük sayılara girerseniz, kaputun altında libgmp kullanır, bu da daha hızlı keyfi hassas kütüphanelerden biridir.


4

yakutta yaş aldı, ancak doğru cevabı verdi:

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

4

Php doğru sonucu elde etmek için BC matematik operatörleri kullanmanız gerektiğini düşünüyorum: http://php.net/manual/en/ref.bc.php

İşte Scala'da doğru cevap. Longs kullanmanız gerekir, aksi takdirde sayıyı taşarsınız:

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

3

Aslında bu sorunun havalı bir hilesi var.

Bunun yerine 1-100 olduğunu varsayın.

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

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

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

Formül:

N = 100 için: Çıkış = N / 2 * (N + 1)

N = 1e9 için: Çıkış = N / 2 * (N + 1)

Bu, tüm verilerin arasında dolaşmaktan çok daha hızlıdır. İşlemciniz bunun için size teşekkür edecek. Ve işte bu problemle ilgili ilginç bir hikaye:

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


11
Kaliningrad'daki Pregel üzerinden her köprüyü iki kez geçmeden yürümek mümkün olabilir mi? Birçok insan denedi ve başarısız oldu, ama kimse bunun imkansız olduğunu henüz belirlemedi. Bu, benzersiz bir şekilde çözmeniz gereken bir zorluk gibi görünüyor.
jwg

3

Bu, tamsayı almayı zorlayarak PHP'de doğru sonucu verir.

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

3

Common Lisp en hızlı yorumlanan * dillerden biridir ve varsayılan olarak keyfi olarak büyük tamsayıları doğru şekilde işler. SBCL ile bu işlem yaklaşık 3 saniye sürer :

* (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
  • Yorumlandığında, bu kodu REPL'den çalıştırdım, SBCL, hızlı çalışmasını sağlamak için dahili olarak bazı JIT'ler yapmış olabilir, ancak kod çalıştırma dinamik deneyimi hemen aynıdır.

Basitleştirilebilir (zaman (x için 1 ile 1000000000 toplam x arasında döngü)). Beyan ekleyerek ~ 5x hız aldım: (zaman (yerel olarak (beyan (optimize et (hız 3) (güvenlik 0))) (1 ila 1000000000 toplam i-tip fixnum i tipi için döngü))
huaiyuan

Bu hatalı. Diğer diller tarafından kör olmanıza izin vermeyin! Lisp'de yazmanın doğru yolu: (defun sum-1-to-n (n) (/ (* n (1+ n)) 2)) (time (sum-to-1-n-n) 1000000000)) çalıştırmak için 14 mikrosaniye (0.000014 saniye) sürdü. Bu süre zarfında ve mevcut 4 CPU çekirdeği ile, kullanıcı modunda 0 mikrosaniye (0.000000 saniye) harcanmıştır 0 mikrosaniye (0.000000 saniye) sistem modunda -> 500000000500000000
informatimago

@informatimago: Hatalı değil. Sorunun zorunlu döngü tarzını kopyalıyordum ve birçok kişinin belirttiği gibi, sorunun kendisi hesaplamanın daha kolay bir yolundan bahsediyor. Chillax.
postfuturist

3

@ Postfuturist'in Common Lisp cevabı hakkında yorum yapmak için yeterli üne sahip değilim, ancak makinemde SBCL 1.1.8 ile ~ 500ms içinde tamamlamak için optimize edilebilir:

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

Raket v 5.3.4 (MBP; ms olarak süre):

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

1
Sizinkini fark ettikten 6 dakika sonra cevabımı sildim. :)
Greg Hendershott

3

Rebol'da iyi çalışıyor:

>> sum: 0
== 0

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

>> type? sum
== integer!

Bu 32 bit derlenmiş olmasına rağmen 64 bit tamsayılar kullanan 32 bit tamsayı kullanan Rebol 3'ü kullanıyordu.


3

CF Script'te neler olduğunu görmek istedim

<cfscript>
ttl = 0;

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

5.00000000067E + 017 aldım

Bu oldukça düzgün bir deneydi. Ben bunu biraz daha fazla çaba ile biraz daha iyi kodlanmış olabilir eminim.


3

32bit pencerelerde ActivePerl v5.10.1, intel core2duo 2.6:

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

sonuç: 5 dakika içinde 5.00000000067109e + 017.

"Use bigint" script ile iki saat çalıştı ve daha fazla işe yarayacaktı, ama durdum. Çok yavaş.


Herkes bu kadar büyük nokta eklemenin gerçekten ne kadar sürdüğünü doğrulayabilir mi?
jwg

3

Bütünlük uğruna, Clojure'da (güzel ama çok verimli değil):

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

1
$ MY_FAVOURITE_LANGUAGE cevapların sahip olduğu sadece küçük yararlı bir sonuç
sağlarsa

@jwg evet üzgünüm hattın sonunu kaçırdım - güncellenmiş cevap.
Blacksad

3

AWK:

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

PHP ile aynı yanlış sonucu üretir:

500000000067108992

AWK, sayılar gerçekten büyük olduğunda kayan nokta kullanıyor gibi görünüyor, bu yüzden en azından cevap doğru büyüklük sırası.

Test çalıştırmaları:

$ 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

Yorumlanan diğer dil kategorisi:

Tcl:

Tcl 8.4 veya daha eski bir sürümü kullanıyorsanız 32 veya 64 bit ile derlenmiş olmasına bağlıdır. (8.4 yaşamın sonu).

Rasgele büyük tamsayılara sahip Tcl 8.5 veya daha yenisi kullanılıyorsa, doğru sonucu görüntüler.

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

Bayt derlemesi için testi bir proc'un içine koydum.


2

PHP kodu için cevaptır burada :

Tamsayının boyutu platforma bağlıdır, ancak yaklaşık iki milyarlık bir maksimum değer olağan değerdir (32 bit imzalı). 64 bit platformlar genellikle maksimum 9E18 değerine sahiptir. PHP imzasız tam sayıları desteklemez. Tamsayı boyutu, PHP_.0_SIZE sabiti kullanılarak ve PHP 4.4.0 ve PHP 5.0.5'ten beri PHP_INT_MAX sabiti kullanılarak maksimum değer ile belirlenebilir.


2

Liman:

proc Main()

   local sum := 0, i

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

   ? sum

   return

İçindeki sonuçlar 500000000500000000. (hem windows / mingw / x86 hem de osx / clang / x64 üzerinde)


2

Erlang çalışır:

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).

Sonuçlar: 41> yararsız: from_sum (1.1000000000). 500000000500000000


2

Komik bir şey, PHP 5.5.1, 499999999500000000 (~ 30s olarak) verirken, Dart2Js 500000000067109000 (bu, beklenen JS olduğundan beklenen) verir. CLI Dart doğru cevabı anında veriyor.


2

Erlang beklenen sonucu da verir.

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).

Ve kullanarak:

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

2

smalltalk:

(1 to: 1000000000) inject: 0 into: [:subTotal :next | subTotal + next ]. 

"500000000500000000"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.