为了账号安全,请及时绑定邮箱和手机立即绑定

如何在不使用“/”和“%”的情况下有效地获得商和余数?

如何在不使用“/”和“%”的情况下有效地获得商和余数?

Go
慕容森 2021-12-20 10:59:41
我实现了一个简单的函数,当除数是 的幂时,它返回商和余数10:func getQuotientAndRemainder(num int64, digits uint) (int64, int64) {    divisor := int64(math.Pow(10, float64(digits)))    if num >= divisor {        return num / divisor, num % divisor    } else {        return 0, num    }}只是好奇,除了直接使用/和%运算符,有没有更好的算法来获得商和余数?还是仅在除数是 的幂的情况下10?
查看完整描述

2 回答

?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

return num / divisor, num % divisor

“算法”是健全的,并且可以说是最好的方式:富有表现力。如果有的话,这部分代码可能过于复杂:

int64(math.Pow(10, float64(digits)))

来回转换 float64可以说是次优的。此外,10 的任何大于 18 的幂都会溢出int64。我建议您添加健全性检查并用乘法循环替换代码并测量其性能。

但是:如果您关心性能,只需在汇编中实现它。


查看完整回答
反对 回复 2021-12-20
?
万千封印

TA贡献1891条经验 获得超3个赞

显然,您应该运行一些 Go 基准测试:基准测试、包测试。


您的解决方案看起来效率不高。试试这个:


package main


import "fmt"


func pow(base, exp int64) int64 {

    p := int64(1)

    for exp > 0 {

        if exp&1 != 0 {

            p *= base

        }

        exp >>= 1

        base *= base

    }

    return p

}


func divPow(n, base, exp int64) (q int64, r int64) {

    p := pow(base, exp)

    q = n / p

    r = n - q*p

    return q, r

}


func main() {

    fmt.Println(divPow(42, 10, 1))

    fmt.Println(divPow(-42, 10, 1))

}

输出:


4 2

-4 -2

基准:


BenchmarkDivPow                     20000000            77.4 ns/op

BenchmarkGetQuotientAndRemainder     5000000           296 ns/op


查看完整回答
反对 回复 2021-12-20
  • 2 回答
  • 0 关注
  • 172 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信