Performing basic math using Gauss's sum for Arithmetic progression gives wrong answer in Swift

I am working on a simple project where I try to compute sum using Gauss's technic for summing Arithmetic series with the following data sets.

first term (a1) = 1
nthTerm (n) = 5
commonDifference (d) = 2

/*
Gauss formula
 Sn= n/2[2A1 + (n-1)d]
*/
let a1 = 1
let n = 5
let d = 2
let sum = n / 2 * (2 * a1 + (n - 1) * d)
print("sum =  \(sum)") 
// Expected -> sum = 25
// Swift answer -> sum =  20 ❓

I tested the same code in Python and Javascript both of them gives the correct answer (25) but swift gives the answer as 20.

Am I missing something or there is a bug in Swift?

You're using Swift's integer numeric types. For example, print(n / 2) will actually print 2, not 2.5.

You can use floating-point numbers instead, for example by adding ".0" to the ends of the literals:

let a1 = 1.0  // <- ".0" makes it a floating-point literal
let n = 5.0
let d = 2.0

let sum = n / 2 * ((2 * a1) + ((n - 1) * d)) 
print("sum =  \(sum)")  // "sum = 25.0"

Or by explicitly asking for a floating-point type:

let a1: Double = 1  // <- Same as above
let n: Double = 5
let d: Double = 2
1 Like

That fixed the issue,thanks a lot @Karl :slight_smile:

1 Like

You can do this in integers, just move the division to the end.

1 Like

Thanks for your suggestion @Nevin, I just tested it, interestingly it only works if multiplication happens first but if I change the sum declaration to: -

let sum =  (2 * a1 + (n - 1) * d) * ( n / 2) // ->  20 🤔

// but as you suggested 
let sum =  (2 * a1 + (n - 1) * d) * n / 2 // -> 25 

Changing operator precedence will cause the first issue of Swift's integer numeric type to occur as mentioned by Karl.
So I think it's safer to go with casting to double almost all the time to avoid un-expected precedence bugs.

Previously sent as a dm, reposted here now that the topic has come back from the spam filter:

Actually, what @Nevin suggested is "safer" than using Double or any other floating-point type.

So long as you put off the division until the last moment, the dividend (twice the sum) is always divisible by the divisor (2).

If you use a floating-point type, it's not guaranteed that you can get an accurate result. Because not all integer values can be represented precisely by Double, and those can not are rounded. For example:

let a₁: Double = 1
let n: Double = 4611686018427387902
let d: Double = 0

let sum = n / 2 * ((2 * a₁) + ((n - 1) * d))
print(sum) // prints "4.611686018427388e+18"
2 Likes

Thanks once again @wowbagger , I really appreciate your detailed explanation.

I missed the point when @Nevin mentioned about moving the division to the end. With this detailed explanation it all make it clear now :raised_hands:.