2013-08-20 10 views
7

Tak więc, wczoraj podczas pracy przez jakiś kod F # jako część ćwiczenia kodowania, inny programista wskazał coś ciekawego. Właśnie zrobiliśmy krótki fragment kodu, aby zademonstrować zsumowanie listy. Jeśli mam zrobić:Jak zdobyć listę zmniejszyć przepełnienie arytmetyczne

[1..100000] |> Seq.sum 

pojawia się następujący błąd:

System.OverflowException: Arithmetic operation resulted in an overflow. 
    at <StartupCode$FSI_0003>[email protected]() 
Stopped due to error 

Jednak jeśli mam zrobić:

[1..100000] |> List.reduce (+) 

uzyskać:

val it : int = 705082704 

Zdaję sobie sprawę, chociaż te dwa kawałki kodu powinny osiągnąć ten sam p przypuszczam, że są bardzo różne. Jestem tylko ciekawy, czy istnieje sposób, aby List.reduce rzucić wyjątek OverflowException, a nie dać mi złą odpowiedź?

+1

Tylko dodatek do istniejących odpowiedzi: suma "1..100000 = (100001 * 100000)/2 = 50000 50000 = 0x12A06B550' który jest przepełnieniem. Upuszczenie bitu przepełnienia: '0x12A06B550 - 0x100000000 = 0x2A06B550 = 705082704'. – bytebuster

Odpowiedz

7

Można użyć sprawdzonego operatora.

[1..100000] |> List.reduce (Checked.(+)) 
7

z kodu C# source

[<CompiledName("Sum")>] 
let inline sum (source: seq< (^a) >) : ^a = 
    use e = source.GetEnumerator() 
    let mutable acc = LanguagePrimitives.GenericZero< (^a) > 
    while e.MoveNext() do 
     acc <- Checked.(+) acc e.Current 
    acc 

zauważy sprawdzone (operator) Ten sprawdza przepełnienie ...

http://msdn.microsoft.com/en-us/library/vstudio/ee340296.aspx

Powiązane problemy