Résultats inattendus lorsque vous travaillez avec de très grands entiers sur des langages interprétés

192

Je suis en train d'obtenir la somme 1 + 2 + ... + 1000000000, mais je suis d' obtenir des résultats amusants en PHP et Node.js .

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

La bonne réponse peut être calculée en utilisant

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

Bonne réponse = 500000000500000000 , j'ai donc décidé d'essayer une autre langue.

ALLER

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

Mais ça marche bien! Alors, quel est le problème avec mon code PHP et Node.js?

C'est peut-être un problème de langages interprétés, et c'est pourquoi cela fonctionne dans un langage compilé comme Go? Dans l'affirmative, d'autres langages interprétés tels que Python et Perl auraient-ils le même problème?

Baba
la source
36
vous en avez besoin: php.net/manual/en/book.bc.php , sinon vous vous ferez la tête contre IEEE 754 jusqu'à ce que l'enfer gèle.
tereško
5
Pour gérer de grands nombres en PHP (c'est-à-dire 64 bits), utilisez les fonctions GMP, dans ce cas gmp_add ().
Jeffrey
113
Pour une super efficacité, vos boucles devraient vraiment commencer à 1 au lieu de 0.: P
Graham Borland
55
somme (1 à N) = (N / 2) * (N + 1)
Phong
5
@Baba 0 est superflu pour votre calcul, il n'est donc pas nécessaire d'avoir une itération supplémentaire de la boucle pour ajouter 0 à 0.
Brian Warshaw

Réponses:

155

Python fonctionne:

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

Ou:

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

intAuto de Python se transforme en Python longqui prend en charge la précision arbitraire. Il produira la bonne réponse sur les plates-formes 32 ou 64 bits.

Cela peut être vu en élevant 2 à une puissance bien supérieure à la largeur de bit de la plate-forme:

>>> 2**99
633825300114114700748351602688L

Vous pouvez démontrer (avec Python) que les valeurs erronées que vous obtenez en PHP sont dues au fait que PHP se transforme en flottant lorsque les valeurs sont supérieures à 2 ** 32-1:

>>> int(sum(float(x) for x in xrange(1000000000+1)))
500000000067108992
dawg
la source
Avez-vous exécuté cela sur un système 32 ou 64 bits?
Baba
4
Cela devrait fonctionner indépendamment (32 vs 64 bits) car les entrées Python promeuvent automatiquement avec une précision arbitraire plutôt que de déborder. Cela pourrait prendre un peu plus de temps.
dawg
3
Python sur n'importe quel système fonctionnera dans ce cas, car Python passe automatiquement aux entiers longs si nécessaire. Et si cela ne suffit pas, il passera également aux grands nombres entiers.
Alok Singhal
12
@ 0x499602D2: C'est un peu dur. Le PO lui-même l'a voté. Il a demandé spécifiquement s'il s'agissait d'un problème similaire sur Python. Réponse, non, ce n'est pas le cas. Code pour montrer que ce n'est pas le cas. WTH?
dawg
10
L'exemple Python est trop long, utilisez simplement sum (xrange (int (1e9) +1)) (.... sum fonctionne sur les itérables)
Jason Morgan
101

Votre code Go utilise une arithmétique entière avec suffisamment de bits pour donner une réponse exacte. Je n'ai jamais touché PHP ou Node.js, mais d'après les résultats, je soupçonne que les calculs sont effectués en utilisant des nombres à virgule flottante et devraient donc ne pas être exacts pour des nombres de cette ampleur.

zzzz
la source
46
Oui. 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
Et dans NodeJS (et JavaScript en général), toutes les opérations arithmétiques (à l'exception des opérations sur les bits) se comportent comme si elles étaient effectuées avec des nombres à virgule flottante. Qu'ils le soient ou non, c'est une distinction sous le capot soumise aux décisions des moteurs JavaScript individuels.
Peter Olson
13
Dans la spécification de javascript, il n'y a pas de types entiers. Tous les nombres sont des virgules flottantes.
toasted_flakes
8
@grasGendarme Il y en a. La spécification ES5 spécifie diverses conversions entières et exige qu'elles soient appelées par décalage au niveau du bit , par exemple. C'est-à-dire en coulisses , les types entiers sont utilisés en Javascript, mais tous les opérateurs arithmétiques convertissent leurs opérandes en nombres à virgule flottante avant de faire quoi que ce soit avec eux (sauf optimisation du compilateur).
Peter Olson
2
voici le code je suppose que son foiré parce que j'ai utilisé float64 et non int64 .. Je viens de confirmer qu'il n'a rien à voir avec 32 ou 64 bits
Baba
45

La raison en est que la valeur de votre variable entière sumdépasse la valeur maximale. Et le sumrésultat obtenu est le résultat d'une arithmétique à virgule flottante qui implique l'arrondi. Étant donné que d'autres réponses ne mentionnaient pas les limites exactes, j'ai décidé de l'afficher.

La valeur entière maximale pour PHP pour:

  • La version 32 bits est 2147483647
  • La version 64 bits est 9223372036854775807

Cela signifie donc que vous utilisez un processeur 32 bits ou un système d'exploitation 32 bits ou une version compilée 32 bits de PHP. Il peut être trouvé en utilisant PHP_INT_MAX. Le sumserait calculé correctement si vous le faites sur une machine 64 bits.

La valeur entière maximale en JavaScript est 9007199254740992 . La plus grande valeur intégrale exacte avec laquelle vous pouvez travailler est 2 53 (tirée de cette question ). Le sumdépasse cette limite.

Si la valeur entière ne dépasse pas ces limites, alors vous êtes bon. Sinon, vous devrez rechercher des bibliothèques d'entiers de précision arbitraire.

utilisateur568109
la source
28

Voici la réponse en C, pour être complet:

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

La clé dans ce cas est d'utiliser le long long type de données de C99 . Il fournit le plus grand stockage primitif que C puisse gérer et il fonctionne vraiment, très rapidement. Le long longtype fonctionnera également sur la plupart des machines 32 ou 64 bits.

Il y a une mise en garde: les compilateurs fournis par Microsoft ne prennent explicitement pas en charge la norme C99 vieille de 14 ans, donc le faire fonctionner dans Visual Studio est un crapshot.

CyberSkull
la source
3
MSVC ++ est un compilateur C ++, et C ++ est entré long longdans la norme C ++ 11. Il s'agit cependant d'une extension MSVC ++ et g ++ depuis quelques années.
MSalters
1
@MSalters Donc, étant une fonctionnalité C ++, cela n'aidera vraiment personne à compiler un programme C simple. Je n'ai jamais essayé de passer du C au C ++, donc je ne sais pas si cette solution de contournement fonctionnerait réellement.
CyberSkull
19
Et bien, GCC ou Clang avec des optimisations transforment toute la boucle enmovabsq $500000000500000000, %rsi
Tor Klingberg
3
Juste gcc -O3ou clang -O3. Je ne connais pas le nom de l'optimisation spécifique. Fondamentalement, le compilateur remarque que le résultat de la boucle ne dépend d'aucun argument et le calcule au moment de la compilation.
Tor Klingberg
1
C99 long long a une taille minimale de 64 bits et, à ma connaissance, est de 64 bits sur les plates-formes 32 bits et 64 bits. Je n'ai pas vu de support général pour les ints quad ou octo.
Devin Lane
21

Je suppose que lorsque la somme dépasse la capacité d'un natif int(2 31 -1 = 2 147 483 647), Node.js et PHP passent à une représentation en virgule flottante et vous commencez à obtenir des erreurs d'arrondi. Un langage comme Go essaiera probablement de conserver une forme entière (par exemple, des entiers 64 bits) aussi longtemps que possible (si, en effet, cela n'a pas commencé par cela). Puisque la réponse tient dans un entier 64 bits, le calcul est exact.

Ted Hopp
la source
Node.js n'a explicitement pas de type int. Cela fonctionne dans un type flottant.
greyfade
@greyfade - Ouais, je suppose que c'est vrai pour tous les environnements conformes à EcmaScript.
Ted Hopp
N'est-ce pas (2 ** 31 - 1)?
Zachary Hunter
@ZacharyHunter - En effet. Merci d'avoir rattrapé cette erreur.
Ted Hopp
19

Le script Perl nous donne le résultat attendu:

use warnings;
use strict;

my $sum = 0;
for(my $i = 0; $i <= 1_000_000_000; $i++) {
    $sum += $i;
}
print $sum, "\n";  #<-- prints: 500000000500000000
Miguel Prz
la source
3
Avez-vous exécuté cela sur un système 32 ou 64 bits?
Baba
2
il a été exécuté sur un système 64 bits
Miguel Prz
3
4.99999999067109e+017sur Perl v5.16.1 MSWin32-x86.
Qtax
7
Si vous avez vraiment besoin de grands nombres, utilisez le bignumou bigint. Les deux sont des modules de base, c'est-à-dire qu'ils sont installés avec Perl v5.8.0 ou supérieur. Voir http://perldoc.perl.org/bignum.htmlethttp://perldoc.perl.org/bigint.html
shawnhcorey
J'ai obtenu 500000000500000000 en cours d'exécution sur un Mac PPC 32 bits, exécutant Perl 5.12.4.
CyberSkull
17

La réponse à cette question est "étonnamment" simple:

Tout d'abord - comme la plupart d'entre vous le savent peut-être - un entier 32 bits varie de −2 147 483 648 à 2 147 483 647 . Alors, que se passe-t-il si PHP obtient un résultat, c'est PLUS GRAND que cela?

Habituellement, on s'attendrait à un "débordement" immédiat, entraînant la conversion de 2 147 483 647 + 1 en −2 147 483 648 . Cependant, ce n'est pas le cas. SI PHP rencontre un plus grand nombre, il renvoie FLOAT au lieu de INT.

Si PHP rencontre un nombre au-delà des limites du type entier, il sera plutôt interprété comme un flottant. En outre, une opération qui aboutit à un nombre au-delà des limites du type entier retournera un flottant à la place.

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

Cela dit, et sachant que l'implémentation de PHP FLOAT suit le format double précision IEEE 754, cela signifie que PHP est capable de gérer des nombres jusqu'à 52 bits, sans perdre en précision. (Sur un système 32 bits)

Ainsi, au point où votre somme atteint 9 007 199 254 740 992 (ce qui est 2 ^ 53 ) La valeur flottante renvoyée par les mathématiques PHP ne sera plus assez précise.

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

Cet exemple montre le point, où PHP perd de sa précision. Tout d'abord, le dernier bit significatif sera supprimé, ce qui entraînera les 2 premières expressions à donner un nombre égal - ce qu'elles ne sont pas.

À partir de NOW ON, toutes les mathématiques iront mal, lorsque vous travaillez avec des types de données par défaut.

• Est-ce le même problème pour d'autres langages interprétés tels que Python ou Perl?

Je ne pense pas. Je pense que c'est un problème de langues qui n'ont aucune sécurité de type. Bien qu'un débordement d'entier comme mentionné ci-dessus se produise dans toutes les langues qui utilisent des types de données fixes, les langues sans sécurité de type peuvent essayer d'attraper cela avec d'autres types de données. Cependant, une fois qu'ils ont atteint leur frontière "naturelle" (donnée par le système) - ils pourraient retourner n'importe quoi, mais le bon résultat.

Cependant, chaque langue peut avoir des threads différents pour un tel scénario.

dognose
la source
15

Les autres réponses ont déjà expliqué ce qui se passe ici (précision en virgule flottante comme d'habitude).

Une solution consiste à utiliser un type entier suffisamment grand, ou à espérer que la langue en choisira un si nécessaire.

L'autre solution consiste à utiliser un algorithme de sommation qui connaît le problème de précision et le contourne. Vous trouverez ci-dessous la même somme, d'abord avec un entier 64 bits, puis avec une virgule flottante 64 bits, puis en utilisant à nouveau la virgule flottante, mais avec l' algorithme de sommation de Kahan .

Écrit en C #, mais il en va de même pour les autres langues.

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

La sommation Kahan donne un beau résultat. Cela prend bien sûr beaucoup plus de temps à calculer. Votre utilisation dépend a) de vos besoins en termes de performances et de précision, et b) de la manière dont votre langage gère les types de données entiers ou à virgule flottante.

linac
la source
@Baba C'est la même chose qu'avec Node.js / JavaScript dans l'OP. Quant à savoir pourquoi 500000000067109000 contre 500000000067108992… aucune idée.
linac
Baba est peut-être intrigué par l'utilisation de points pour mille séparateurs: l'anglais attend généralement des virgules. Vous pouvez également utiliser des soulignés comme moyen plus neutre.
didierc
14

Si vous avez du PHP 32 bits, vous pouvez le calculer avec bc :

<?php

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

En Javascript, vous devez utiliser une bibliothèque de nombres arbitraires, par exemple BigInteger :

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

Même avec des langages comme Go et Java, vous devrez éventuellement utiliser une bibliothèque de nombres arbitraires, votre numéro était juste assez petit pour 64 bits mais trop élevé pour 32 bits.

Esailija
la source
12

En rubis:

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

Imprime 500000000500000000, mais prend 4 bonnes minutes sur mon processeur Intel i7 2,6 GHz.


Magnuss et Jaunty ont une solution beaucoup plus Ruby:

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

Pour exécuter un benchmark:

$ 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
cgenco
la source
10
1. upto (1000000000) .inject (: +)
Magnuss
@Magnuss: C'est ce que je pensais avoir essayé au début, mais cela a provoqué une fuite de mémoire massive. Le tien semble fonctionner ...
cgenco
11

J'utilise node-bigint pour les gros trucs entiers:
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);

Ce n'est pas aussi rapide que quelque chose qui peut utiliser des éléments natifs 64 bits pour ce test exact, mais si vous entrez en plus grand nombre que 64 bits, il utilise libgmp sous le capot, qui est l'une des bibliothèques de précision arbitraire les plus rapides du marché.

Eve Freeman
la source
4

a pris des âges en rubis, mais donne la bonne réponse:

(1..1000000000).reduce(:+)
 => 500000000500000000 
Jauny
la source
4

Pour obtenir le résultat correct en php, je pense que vous devez utiliser les opérateurs mathématiques de la Colombie-Britannique: http://php.net/manual/en/ref.bc.php

Voici la bonne réponse dans Scala. Vous devez utiliser Longs sinon vous débordez le nombre:

println((1L to 1000000000L).reduce(_ + _)) // prints 500000000500000000
sous-protocole
la source
3

Il y a en fait une astuce sympa à ce problème.

Supposons que c'était 1-100 à la place.

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

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

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

Formule:

Pour N = 100: Sortie = N / 2 * (N + 1)

Pour N = 1e9: Sortie = N / 2 * (N + 1)

C'est beaucoup plus rapide que de parcourir toutes ces données. Votre processeur vous en remerciera. Et voici une histoire intéressante concernant ce problème:

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

user2522001
la source
11
Pensez-vous qu'il soit possible de traverser tous les ponts du Pregel à Kaliningrad, sans traverser deux ponts? Beaucoup de gens ont essayé et échoué, mais personne n'a encore établi que c'était impossible. Cela semble être un défi que vous seriez particulièrement qualifié pour résoudre.
jwg
3

Cela donne le bon résultat en PHP en forçant le transtypage entier.

$sum = (int) $sum + $i;
ck_
la source
3

Common Lisp est l'un des langages * les plus rapidement interprétés et gère par défaut les entiers arbitrairement grands. Cela prend environ 3 secondes avec SBCL :

* (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
  • Par interprété, je veux dire, j'ai exécuté ce code à partir du REPL, SBCL peut avoir fait du JIT en interne pour le faire fonctionner rapidement, mais l'expérience dynamique de l'exécution immédiate du code est la même.
postfuturiste
la source
Peut être simplifié comme (temps (boucle pour x de 1 à 1000000000 somme x)). J'ai obtenu une vitesse ~ 5x en ajoutant la déclaration: (time (localement (declare (optimise (vitesse 3) (sécurité 0)))) (boucle pour i de type fixnum de 1 à 1000000000 somme i de type fixnum)))
huaiyuan
C'est erroné. Ne vous laissez pas aveugler par les autres langues! La façon correcte de l'écrire dans lisp est: (defun sum-from-1-to-n (n) (/ (* n (1+ n)) 2)) (time (sum-from-1-to-n 1000000000)) a pris 14 microsecondes (0,000014 secondes) pour fonctionner. Pendant cette période, et avec 4 cœurs CPU disponibles, 0 microsecondes (0,000000 secondes) ont été dépensées en mode utilisateur 0 microsecondes (0,000000 secondes) ont été dépensées en mode système -> 500000000500000000
informatimago
@informatimago: Ce n'est pas erroné. Je copiais le style de boucle impératif de la question et comme beaucoup l'ont souligné, la question elle-même mentionne qu'il existe un moyen plus simple de calculer. Chillax.
postfuturiste
3

Je n'ai pas assez de réputation pour commenter la réponse Common Lisp de @ postfuturist, mais elle peut être optimisée pour se terminer en ~ 500 ms avec SBCL 1.1.8 sur ma machine:

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
jdtw
la source
3

Racket v 5.3.4 (MBP; temps en ms):

> (time (for/sum ([x (in-range 1000000001)]) x))
cpu time: 2943 real time: 2954 gc time: 0
500000000500000000
Fleur de Keith
la source
1
J'ai supprimé ma réponse postée 6 minutes après vous, une fois que j'ai remarqué la vôtre. :)
Greg Hendershott
3

Fonctionne bien dans Rebol:

>> sum: 0
== 0

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

>> type? sum
== integer!

Cela utilisait Rebol 3 qui, bien que compilé en 32 bits, utilise des entiers 64 bits (contrairement à Rebol 2 qui utilisait des entiers 32 bits)

draegtun
la source
3

Je voulais voir ce qui s'est passé dans CF Script

<cfscript>
ttl = 0;

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

J'ai eu 5.00000000067E + 017

Ce fut une expérience assez soignée. Je suis presque sûr que j'aurais pu coder cela un peu mieux avec plus d'effort.

georgiamadkow
la source
3

ActivePerl v5.10.1 sous Windows 32 bits, Intel Core2duo 2.6:

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

résultat: 5.00000000067109e + 017 en 5 minutes.

Avec "use bigint", le script a fonctionné pendant deux heures et aurait fonctionné davantage, mais je l'ai arrêté. Trop lent.

Sournois
la source
Quelqu'un peut-il confirmer que c'est vraiment combien de temps cela prend autant de bigints?
jwg
3

Par souci d'exhaustivité, dans Clojure (beau mais pas très efficace):

(reduce + (take 1000000000 (iterate inc 1))) ; => 500000000500000000
Blacksad
la source
1
Le seul petit élément utile des réponses $ MY_FAVOURITE_LANGUAGE est qu'elles fournissent le résultat ...
jwg
@jwg ouais désolé, j'ai raté la fin de la ligne - réponse mise à jour.
Blacksad
3

AWK:

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

produit le même mauvais résultat que PHP:

500000000067108992

Il semble qu'AWK utilise des virgules flottantes lorsque les nombres sont vraiment grands, donc au moins la réponse est le bon ordre de grandeur.

Essais:

$ 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
QuasarDonkey
la source
2

Catégorie autre langage interprété:

Tcl:

Si vous utilisez Tcl 8.4 ou une version antérieure, cela dépend si elle a été compilée avec 32 ou 64 bits. (8.4 est la fin de vie).

Si vous utilisez Tcl 8.5 ou plus récent qui a de grands nombres entiers arbitraires, il affichera le résultat correct.

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

J'ai mis le test dans un proc pour le compiler en octets.

Johannes Kuhn
la source
2

Pour le code PHP, la réponse est ici :

La taille d'un entier dépend de la plate-forme, bien qu'une valeur maximale d'environ deux milliards soit la valeur habituelle (c'est-à-dire 32 bits signés). Les plates-formes 64 bits ont généralement une valeur maximale d'environ 9E18. PHP ne prend pas en charge les entiers non signés. La taille entière peut être déterminée en utilisant la constante PHP_INT_SIZE, et la valeur maximale en utilisant la constante PHP_INT_MAX depuis PHP 4.4.0 et PHP 5.0.5.

vicentazo
la source
2

Port:

proc Main()

   local sum := 0, i

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

   ? sum

   return

Résultats en 500000000500000000. (sur les deux fenêtres / mingw / x86 et osx / clang / x64)

vszakats
la source
2

Erlang travaille:

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

Résultats: 41> inutile: from_sum (1,1000000000). 500000000500000000

Steve Moon
la source
2

Chose amusante, PHP 5.5.1 donne 499999999500000000 (en ~ 30s), tandis que Dart2Js donne 500000000067109000 (ce qui est normal, car c'est JS qui est exécuté). CLI Dart donne la bonne réponse ... instantanément.

Doru Moisa
la source
2

Erlang donne aussi le résultat attendu.

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

Et en l'utilisant:

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

Smalltalk:

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

"500000000500000000"
Samuel Henry
la source