Make Int round off to nearest value

2020-02-07 05:59发布

问题:

I've got two Int values (they have to be Ints) and I want them to round off to the nearest value when in an equation;

var Example = Int()
var secondExample = Int()

Example = (secondExample / 7000)

This equation makes the variable Example always round down to the lowest value. Say for example that the numbers are the following;

var Example = Int()
var secondExample : Int = 20000

Example = (20000 / 7000)

20000 / 7000 equals 2.857... But the variable Example displays 2.

How can I make Example round off to closest number without changing it to a Double

回答1:

For nonnegative integers, the following function gives the desired result in pure integer arithmetic :

func divideAndRound(numerator: Int, _ denominator: Int) -> Int {
    return (2 * numerator + denominator)/(2 * denominator)
}

Examples:

print(20000.0/7000.0) // 2.85714285714286
print(divideAndRound(20000, 7000)) // 3 (rounded up)

print(10000.0/7000.0) // 1.42857142857143
print(divideAndRound(10000, 7000)) // 1 (rounded down)

The idea is that

 a   1   2 * a + b
 - + - = ---------
 b   2     2 * b

And here is a possible implementation for arbitrarily signed integers which also does not overflow:

func divideAndRound(num: Int, _ den: Int) -> Int {
    return num / den + (num % den) / (den / 2 + den % 2)
}

(Based on @user3441734's updated solution, so we have a reference cycle between our answers now :)

There is also a ldiv function which computes both quotient and remainder of a division, so the last function could also be implemented as

func divideAndRound(num: Int, _ den: Int) -> Int {
    let div = ldiv(num, den)
    let div2 = ldiv(den, 2)
    return div.quot + div.rem / (div2.quot + div2.rem)
}

(I did not test which version is faster.)



回答2:

see Martin's answer! his idea is great, so i extend his solution for negative numbers

func divideAndRound(n: Int, _ d: Int) -> Int {
    let sn = n < 0 ? -1 : 1
    let sd = d < 0 ? -1 : 1
    let s = sn * sd
    let n = n * sn
    let d = d * sd
    return (2 * n + d)/(2 * d) * s
}

divideAndRound(1, 2) // 1
divideAndRound(1, 3) // 0
divideAndRound(-1, 2) // -1
divideAndRound(-1, 3) // 0
divideAndRound(1, -2) // -1
divideAndRound(1, -3) // 0

the only trouble is that (2 * n + d) can overflow and code will crash.

UPDATE! with help of mathematics for children

func divr(a: Int, _ b: Int)->Int {
    return (a % b) * 2 / b  + a / b
}

it should work for any Int :-) except 0 denominator.