【问题标题】:Make Int round off to nearest value使 Int 四舍五入到最接近的值
【发布时间】:2016-07-22 11:52:32
【问题描述】:

我有两个 Int 值(它们必须是 Int),我希望它们在方程式中四舍五入到最接近的值;

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

Example = (secondExample / 7000)

这个等式使变量Example 总是向下舍入到最小值。例如,数字如下;

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

Example = (20000 / 7000)

20000 / 7000 等于 2.857... 但变量 Example 显示为 2

如何使Example 舍入到最接近的数字而不将其更改为双精度数

【问题讨论】:

  • 我不认为你可以,因为整数是整数,你可以把它改成双精度数,四舍五入,然后再改回来……但我认为这是不可能的。
  • 您使用了错误的数据类型来完成您想要完成的任务。我建议您返回 documentation 以了解 Swift 中可供您使用的不同数据类型。
  • @Brianvandenheuvel 见马丁的回答,没有什么是不可能的。 ;)
  • @RappeStegarn 请看我的更新

标签: swift int double rounding


【解决方案1】:

对于非负整数,以下函数给出 纯整数算术的期望结果:

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

例子:

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)

这个想法是

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

这是任意签名的可能实现 也不会溢出的整数:

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

(基于@user3441734的更新解决方案,所以我们有一个参考 现在在我们的答案之间循环:)

还有一个ldiv 函数可以计算两个商 和除法的余数,所以最后一个函数也可以是 实现为

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

(我没有测试哪个版本更快。)

【讨论】:

  • 如果你使用它,它会更安全地防止溢出:return numerator / divisor + (2 * (numerator % divisor) + ((numerator >= 0) ? 1 : -1) * abs(divisor))/(2 * divisor) - 基本上只是对余数进行四舍五入。
  • @user3441734 刚发帖就看到了,很不错。
  • 感谢您重新排列“我的”公式!我之前投票过你的答案,我想再做一次:-)
  • 谢谢(我也对你的回答做了同样的事情:)棘手的部分是使四舍五入在奇数分母下正确工作。
  • @DuncanC 我不经常看到另一个邓肯在四处游荡。 :)
【解决方案2】:

见马丁的回答!他的想法很棒,所以我扩展了他的负数解决方案

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

唯一的问题是 (2 * n + d) 会溢出,代码会崩溃。

更新!在儿童数学的帮助下

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

它应该适用于除 0 分母以外的任何 Int :-)

【讨论】:

  • 我刚刚测试了更新,它的工作原理,不错的算法。
  • 好主意,但实际上(a % b) * 2 可以 溢出,试试divideAndRound(9223372036854775643, 9223372036854775783) :)
  • 我认为你错了。如果 0
  • @MartinR 我删除了我的愚蠢笔记:-),我正在洗澡....会在一小时内检查。提前谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多