Risultati imprevisti quando si lavora con numeri interi molto grandi su linguaggi interpretati


192

Sto cercando di ottenere la somma di 1 + 2 + ... + 1000000000, ma sto ottenendo risultati divertenti in PHP e 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 risposta corretta può essere calcolata utilizzando

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

Risposta corretta = 500000000500000000 , quindi ho deciso di provare un'altra lingua.

PARTIRE

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

Ma funziona benissimo! Cosa c'è di sbagliato nel mio codice PHP e Node.js?

Forse questo è un problema di lingue interpretate ed è per questo che funziona in una lingua compilata come Go? In tal caso, altri linguaggi interpretati come Python e Perl avrebbero lo stesso problema?


36
hai bisogno di questo: php.net/manual/en/book.bc.php , altrimenti ti sbatterai la testa contro IEEE 754 fino a quando l'inferno non si congelerà.
Tereško,

5
Per gestire grandi numeri in PHP (ovvero 64 bit), utilizzare le funzioni GMP, in questo caso gmp_add ().
Jeffrey,

113
Per una super efficienza, i tuoi loop dovrebbero davvero iniziare da 1 invece di 0.: P
Graham Borland

55
somma (da 1 a N) = (N / 2) * (N + 1)
Phong

5
@Baba 0 è superfluo per il tuo calcolo, quindi non è necessario avere un'iterazione aggiuntiva del loop per aggiungere 0 a 0.
Brian Warshaw,

Risposte:


155

Python funziona:

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

O:

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

L' intauto di Python promuove un Python longche supporta precisione arbitraria. Produrrà la risposta corretta su piattaforme a 32 o 64 bit.

Questo può essere visto aumentando 2 a una potenza molto maggiore della larghezza di bit della piattaforma:

>>> 2**99
633825300114114700748351602688L

Puoi dimostrare (con Python) che i valori errati che stai ottenendo in PHP sono perché PHP sta promuovendo un float quando i valori sono maggiori di 2 ** 32-1:

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

Hai eseguito questo su un sistema a 32 o 64 bit?
Baba,

4
Dovrebbe funzionare indipendentemente (32 vs 64 bit) poiché Python inserisce la promozione automatica con precisione arbitraria anziché overflow. Potrebbe volerci un po 'di più.
dawg

3
Python su qualsiasi sistema funzionerà in questo caso, poiché Python passa automaticamente a numeri interi lunghi, se necessario. E se ciò non bastasse, passerà anche ai numeri interi grandi.
Alok Singhal,

12
@ 0x499602D2: è piuttosto duro. L'OP stesso lo ha votato. Ha chiesto specificamente se questo fosse un problema simile su Python. Risposta, no non lo è. Codice per mostrare che non lo è. WTH?
dawg

10
L'esempio di Python è eccessivamente lungo, basta usare sum (xrange (int (1e9) +1)) (.... sum funziona su iterables)
Jason Morgan

101

Il tuo codice Go utilizza l'aritmetica dei numeri interi con bit sufficienti per fornire una risposta esatta. Non ho mai toccato PHP o Node.js, ma dai risultati sospetto che la matematica sia stata utilizzata numeri in virgola mobile e quindi ci si dovrebbe aspettare che non siano esatti per numeri di questa portata.


46
Sì. 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
E in NodeJS (e JavaScript in generale) tutte le operazioni aritmetiche (tranne le operazioni sui bit) si comportano come se fossero eseguite con numeri in virgola mobile. Il fatto che lo siano o meno è una distinzione nascosta soggetta alle decisioni dei singoli motori JavaScript.
Peter Olson,

13
Nelle specifiche di JavaScript, non ci sono tipi interi. Tutti i numeri sono in virgola mobile.
toasted_flakes

8
@grasGendarme Ci sono. La specifica ES5 specifica varie conversioni di interi e mandati che possono essere chiamati in turni a bit , per esempio. Vale a dire dietro le quinte , i tipi interi sono usati in Javascript, ma tutti gli operatori aritmetici convertono i loro operandi in numeri in virgola mobile prima di fare qualsiasi cosa con loro (salvo le ottimizzazioni del compilatore).
Peter Olson,

2
ecco il codice immagino sia incasinato perché ho usato float64 e non int64 .. Ho appena confermato che non ha nulla a che fare con 32 o 64 bit
Baba,

45

Il motivo è che il valore della variabile intera sumsupera il valore massimo. E ilsum risultato è il risultato dell'aritmetica in virgola mobile che comporta l'arrotondamento. Poiché le altre risposte non menzionavano i limiti esatti, ho deciso di pubblicarlo.

Il valore intero massimo per PHP per:

  • La versione a 32 bit è 2147483647
  • La versione a 64 bit è 9223372036854775807

Quindi significa che stai usando CPU a 32 bit o sistema operativo a 32 bit o versione compilata a 32 bit di PHP. Può essere trovato usando PHP_INT_MAX. Ilsum sarebbe calcolato correttamente se lo si fa su una macchina a 64 bit.

Il valore intero massimo in JavaScript è 9007199254740992 . Il valore integrale esatto più grande con cui puoi lavorare è 2 53 (tratto da questa domanda ). Ilsum supera questo limite.

Se il valore intero non supera questi limiti, allora sei a posto. Altrimenti dovrai cercare librerie di numeri interi di precisione arbitraria.


28

Ecco la risposta in C, per completezza:

#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 chiave in questo caso sta usando il long long tipo di dati di C99 . Fornisce l'archiviazione primitiva più grande che C sia in grado di gestire e funziona davvero, molto velocemente. Il long longtipo funzionerà anche su quasi tutti i computer a 32 o 64 bit.

C'è un avvertimento: i compilatori forniti da Microsoft non supportano esplicitamente lo standard C99 di 14 anni, quindi far funzionare questo in Visual Studio è un crapshot.


3
MSVC ++ è un compilatore C ++ e C ++ è entrato long longnello standard C ++ 11. Tuttavia, è stata un'estensione MSVC ++ e g ++ per alcuni anni.
Saluti

1
@MSalters Quindi, essendo una funzionalità C ++, non sarà davvero d'aiuto a nessuno compilare un programma C diretto. Non ho mai provato a passare da C a C ++, quindi non so se quella soluzione funzionerebbe davvero.
CyberSkull,

19
E bene, GCC o Clang con ottimizzazioni trasformano l'intero ciclo inmovabsq $500000000500000000, %rsi
Tor Klingberg

3
Proprio gcc -O3o clang -O3. Non conosco il nome dell'ottimizzazione specifica. Fondamentalmente il compilatore nota che il risultato del ciclo non dipende da alcun argomento e lo calcola al momento della compilazione.
Tor Klingberg,

1
C99 long long ha una dimensione minima di 64 bit e, per quanto ne so, è 64 bit su piattaforme sia a 32 che a 64 bit. Non ho visto il supporto generale per quad o octo ints.
Devin Lane,

21

La mia ipotesi è che quando la somma supera la capacità di un nativo int(2 31 -1 = 2.147.483.647), Node.js e PHP passano a una rappresentazione in virgola mobile e si iniziano a ricevere errori di arrotondamento. Un linguaggio come Go probabilmente proverà a rimanere con una forma intera (ad esempio, numeri interi a 64 bit) il più a lungo possibile (se, in verità, non è iniziato con quello). Poiché la risposta si inserisce in un numero intero a 64 bit, il calcolo è esatto.


Node.js non ha esplicitamente un tipo int. Funziona in un tipo float.
Greyfade,

@greyfade - Sì, immagino sia vero per tutti gli ambienti compatibili con EcmaScript.
Ted Hopp,

Non è quello (2 ** 31 - 1)?
Zachary Hunter,

@ZacharyHunter - In effetti lo è. Grazie per aver colto quell'errore.
Ted Hopp,

19

Lo script Perl ci dà il risultato atteso:

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
Hai eseguito questo su un sistema a 32 o 64 bit?
Baba,

2
è stato eseguito su un sistema a 64 bit
Miguel Prz il

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

7
Se hai davvero bisogno di grandi numeri, usa il tasto bignumo bigint. Entrambi sono moduli core, ovvero vengono installati con Perl v5.8.0 o versione successiva. Vedi http://perldoc.perl.org/bignum.htmlehttp://perldoc.perl.org/bigint.html
shawnhcorey il

Ho 500000000500000000 in esecuzione su un Mac PPC a 32 bit, con Perl 5.12.4.
CyberSkull

17

La risposta a questa è "sorprendentemente" semplice:

Innanzitutto, come molti di voi sapranno, un numero intero a 32 bit varia da -2,147,483,648 a 2,147,483,647 . Quindi, cosa succede se PHP ottiene un risultato, che è più grande di questo?

Di solito, ci si aspetterebbe un "Overflow" immediato, facendo sì che 2.147.483.647 + 1 si trasformino in -2.147.483.648 . Tuttavia, NON è così. Se PHP incontra un numero maggiore, restituisce FLOAT anziché INT.

Se PHP incontra un numero oltre i limiti del tipo intero, verrà invece interpretato come float. Inoltre, un'operazione che risulta in un numero oltre i limiti del tipo intero restituirà invece un valore float.

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

Detto questo, e sapendo che l'implementazione di PHP FLOAT sta seguendo il formato IEEE 754 a doppia precisione, significa che PHP è in grado di gestire numeri fino a 52 bit, senza perdere precisione. (Su un sistema a 32 bit)

Quindi, nel punto in cui la somma raggiunge 9.007.199.254.740.992 (ovvero 2 ^ 53 ), il valore Float restituito dalla matematica PHP non sarà più sufficientemente preciso.

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

Questo esempio mostra il punto in cui PHP sta perdendo precisione. Innanzitutto, l'ultimo bit significativo verrà eliminato, facendo sì che le prime 2 espressioni producano un numero uguale, cosa che non sono.

Da ora in poi, l'intera matematica andrà male, quando si lavora con tipi di dati predefiniti.

• È lo stesso problema per altri linguaggi interpretati come Python o Perl?

Io non la penso così. Penso che questo sia un problema di lingue che non hanno sicurezza del tipo. Mentre un overflow di numeri interi come menzionato sopra si verificherà in ogni lingua che utilizza tipi di dati fissi, le lingue senza sicurezza del tipo potrebbero tentare di intercettarlo con altri tipi di dati. Tuttavia, una volta colpito il loro confine "naturale" (dato dal sistema), potrebbero restituire qualsiasi cosa, ma il risultato giusto.

Tuttavia, ogni lingua può avere thread diversi per tale scenario.


15

Le altre risposte hanno già spiegato cosa sta succedendo qui (precisione in virgola mobile come al solito).

Una soluzione è usare un tipo intero abbastanza grande, o sperare che la lingua ne scelga uno se necessario.

L'altra soluzione consiste nell'utilizzare un algoritmo di somma che conosce il problema della precisione e aggira il problema. Di seguito trovi la stessa somma, prima con un numero intero a 64 bit, quindi con un virgola mobile a 64 bit e quindi utilizzando nuovamente il virgola mobile, ma con l' algoritmo di somma Kahan .

Scritto in C #, ma lo stesso vale anche per altre lingue.

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 sommatoria di Kahan dà un bellissimo risultato. Ovviamente ci vuole molto più tempo per calcolare. Se si desidera utilizzarlo dipende a) dalle prestazioni rispetto alle esigenze di precisione eb) da come la lingua gestisce i tipi di dati interi vs. virgola mobile.


@Baba È lo stesso di Node.js / JavaScript nell'OP. Sul motivo per cui 500000000067109000 vs. 500000000067108992 ... non ne ho idea.
linac,

Forse Baba è incuriosito dall'uso di punti per migliaia di separatori: l'inglese si aspetta di solito virgole. Puoi anche usare il trattino basso come mezzo più neutro.
didierc,

14

Se hai un PHP a 32 bit, puoi calcolarlo con bc :

<?php

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

In Javascript devi usare una libreria di numeri arbitrari, ad esempio BigInteger :

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

Anche con lingue come Go e Java alla fine dovrai usare una libreria di numeri arbitraria, il tuo numero è appena stato abbastanza piccolo per 64-bit ma troppo alto per 32-bit.


12

In Ruby:

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

Stampa 500000000500000000, ma richiede ben 4 minuti sul mio Intel i7 a 2,6 GHz.


Magnuss e Jaunty hanno una soluzione Ruby molto più:

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

Per eseguire 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

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

@Magnuss: Questo è quello che pensavo di aver provato all'inizio, ma ha causato un'enorme perdita di memoria. Il tuo sembra funzionare ...
cgenco

11

Uso node-bigint per roba con numeri interi grandi:
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);

Non è veloce come qualcosa che può usare roba nativa a 64 bit per questo test esatto, ma se ottieni numeri più grandi di 64 bit, usa libgmp sotto il cofano, che è una delle librerie di precisione arbitrarie più veloci là fuori.


4

ha impiegato anni in rubino, ma dà la risposta corretta:

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

4

Per ottenere il risultato corretto in php penso che dovresti usare gli operatori matematici BC: http://php.net/manual/en/ref.bc.php

Ecco la risposta corretta in Scala. Devi usare Longs altrimenti sbagli il numero:

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

3

In realtà c'è un bel trucco per questo problema.

Supponiamo invece che fosse 1-100.

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

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

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

Formula:

Per N = 100: Uscita = N / 2 * (N + 1)

Per N = 1e9: Uscita = N / 2 * (N + 1)

Questo è molto più veloce del ciclo attraverso tutti quei dati. Il tuo processore ti ringrazierà per questo. Ed ecco una storia interessante riguardo a questo problema:

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


11
Pensi che potrebbe essere possibile attraversare ogni ponte attraverso il Pregel a Kaliningrad, senza attraversare due ponti due volte? Molte persone hanno provato e fallito, ma nessuno ha ancora stabilito che è impossibile. Sembra una sfida che saresti qualificato in modo univoco per risolvere.
jwg

3

Questo dà il risultato corretto in PHP forzando il cast di numeri interi.

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

3

Common Lisp è uno dei linguaggi * interpretati più velocemente e, per impostazione predefinita, gestisce correttamente numeri arbitrariamente grandi. Questa operazione richiede circa 3 secondi con 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
  • Interpretato, intendo, ho eseguito questo codice dal REPL, SBCL potrebbe aver eseguito alcuni JIT internamente per renderlo veloce, ma l'esperienza dinamica dell'esecuzione del codice è immediatamente la stessa.

Può essere semplificato come (tempo (ciclo per x da 1 a 1000000000 somma x)). Ho ottenuto una velocità di ~ 5x aggiungendo la dichiarazione: (tempo (localmente (dichiara (ottimizza (velocità 3) (sicurezza 0))) (loop per i fixnum di tipo da 1 a 1000000000 somma i fixnum di tipo)))
huaiyuan

Questo è errato. Non lasciarti accecare dalle altre lingue! Il modo corretto di scriverlo in lisp è: (defun sum-from-1-to-n (n) (/ (* n (1+ n)) 2)) (time (sum-from-1-to-n 1000000000)) sono stati necessari 14 microsecondi (0,000014 secondi) per l'esecuzione. Durante quel periodo, e con 4 core CPU disponibili, 0 microsecondi (0,000000 secondi) sono stati spesi in modalità utente 0 microsecondi (0,000000 secondi) sono stati spesi in modalità sistema -> 500000000500000000
informatimago

@informatimago: non è errato. Stavo copiando lo stile del ciclo imperativo della domanda e, come molti hanno sottolineato, la domanda stessa menziona che c'è un modo più semplice per calcolare. Chillax.
postfuturista il

3

Non ho abbastanza reputazione per commentare la risposta Common Lisp di @ postfuturist, ma può essere ottimizzato per completare in ~ 500ms con SBCL 1.1.8 sulla mia macchina:

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

Racket v 5.3.4 (MBP; tempo in ms):

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

1
Ho cancellato la mia risposta postata 6 minuti dopo di te, una volta che ho notato la tua. :)
Greg Hendershott il

3

Funziona bene in Rebol:

>> sum: 0
== 0

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

>> type? sum
== integer!

Stava usando Rebol 3 che nonostante fosse compilato a 32 bit, utilizza numeri interi a 64 bit (a differenza di Rebol 2 che utilizzava numeri interi a 32 bit)


3

Volevo vedere cosa è successo in CF Script

<cfscript>
ttl = 0;

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

Ho ottenuto 5.00000000067E + 017

Questo è stato un esperimento piuttosto accurato. Sono abbastanza sicuro che avrei potuto codificarlo un po 'meglio con più sforzo.


3

ActivePerl v5.10.1 su finestre a 32 bit, Intel Core2duo 2.6:

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

risultato: 5.00000000067109e + 017 in 5 minuti.

Con "usa bigint" lo script ha funzionato per due ore e avrebbe funzionato di più, ma l'ho fermato. Troppo lento.


Qualcuno può confermare che è davvero tanto tempo impiegando così tante origini?
jwg

3

Per completezza, in Clojure (bello ma non molto efficiente):

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

1
L'unico piccolo utile che le risposte di $ MY_FAVOURITE_LANGUAGE hanno è se forniscono il risultato ...
jwg

@jwg yeah mi dispiace che ho perso la fine della linea - risposta aggiornata.
Blacksad,

3

AWK:

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

produce lo stesso risultato errato di PHP:

500000000067108992

Sembra che AWK usi il virgola mobile quando i numeri sono davvero grandi, quindi almeno la risposta è il giusto ordine di grandezza.

Esecuzioni di test:

$ 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

Categoria altra lingua interpretata:

Tcl:

Se si utilizza Tcl 8.4 o precedente, dipende se è stato compilato con 32 o 64 bit. (8.4 è la fine della vita).

Se si utilizza Tcl 8.5 o versioni successive con numeri interi grandi arbitrari, verrà visualizzato il risultato corretto.

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

Ho inserito il test in un proc per farlo compilare in byte.


2

Per il codice PHP, la risposta è qui :

La dimensione di un numero intero dipende dalla piattaforma, sebbene un valore massimo di circa due miliardi sia il valore normale (ovvero 32 bit con segno). Le piattaforme a 64 bit hanno in genere un valore massimo di circa 9E18. PHP non supporta numeri interi senza segno. Le dimensioni intere possono essere determinate usando la costante PHP_INT_SIZE e il valore massimo usando la costante PHP_INT_MAX da PHP 4.4.0 e PHP 5.0.5.


2

Porto:

proc Main()

   local sum := 0, i

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

   ? sum

   return

Risultati in 500000000500000000. (su entrambe le finestre / mingw / x86 e osx / clang / x64)


2

Erlang funziona:

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

Risultati: 41> inutili: from_sum (1.1000000000). 500.000.000.500 milioni


2

Cosa divertente, PHP 5.5.1 dà 499999999500000000 (in ~ 30s), mentre Dart2Js dà 500000000067109000 (che è prevedibile, poiché è JS che viene eseguito). CLI Dart dà la risposta giusta ... all'istante.


2

Anche Erlang dà il risultato atteso.

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

E usandolo:

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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.