我们提供安全,免费的手游软件下载!

安卓手机游戏下载_安卓手机软件下载_安卓手机应用免费下载-先锋下载

当前位置: 主页 > 软件教程 > 软件教程

使用移位操作实现整数除法

来源:网络 更新时间:2024-05-05 18:32:06

五一假期,外面的世界人山人海,而在家刷题成了一种不错的休闲方式。我刚好开始写这道题:

给定两个整数`被除数`和`除数`,在不使用乘法、除法和取模运算符的情况下,实现整数除法。整数除法应该向零截断,即去除其小数部分。例如,`8.345`应该截断为`8`,`-2.7335`应该截断为`-2`。

返回`被除数`除以`除数`后的**商**。

**注意:**假设我们只能处理32位有符号整数范围内的整数:`[−231, 231 − 1]`。对于此问题,如果商**严格大于**`231 - 1`,则返回`231 - 1`,如果商**严格小于**`-231`,则返回`-231`。

**示例1:**

输入:被除数 = 10,除数 = 3
输出:3
解释:10/3 = 3.33333.. 截断为3。

**示例2:**

输入:被除数 = 7,除数 = -3
输出:-2
解释:7/-3 = -2.33333.. 截断为-2。

**约束条件:**

- `-231 <= 被除数, 除数 <= 231 - 1` - `除数 != 0`

理解题目要求,不能使用乘法、除法和取模运算符来计算两个给定整数的商。这时我想到可以利用移位操作来实现。

虽然我在工作多年,但实际项目中使用移位操作的情况并不多。

逻辑移位:

- 逻辑移位将位向左或向右移动,并在空位填充零。 - 在左逻辑移位(<<)中,位向左移动,从右侧填充零。 - 在右逻辑移位(>>)中,位向右移动,从左侧填充零。

简单来说,如果1<<2,就是1乘以2的2次方,以此类推。

因此,我的解决方案很明确,处理好被除数和除数的符号,然后通过循环内使用移位操作来计算商:

func divide(dividend int, divisor int) int {
	quotient := 0
	maxInt := math.MaxInt32
	minInt := math.MinInt32
	if divisor == 0 || (dividend == minInt && divisor == -1) {
		return maxInt
	}

	// 确定商的符号
	sign := -1
	if (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0) {
		sign = 1
	}

	// 将被除数和除数转换为正数
	positiveDividend, positiveDivisor := int(math.Abs(float64(dividend))), int(math.Abs(float64(divisor)))

	for positiveDividend >= positiveDivisor {
		shift := 0
		for positiveDividend >= (positiveDivisor << shift) {
			shift += 1
		}

		quotient += (1<< (shift - 1))
		positiveDividend -= (positiveDivisor << (shift - 1))
	}
	
	return int(math.Min(float64(maxInt), math.Max(float64(sign) * float64(quotient), float64(minInt))))
}

总结

移位操作虽然好,但并非唯一解,回忆小时候还没学乘法时,我们也可以用加法模拟乘法,因此利用累加来模拟两数之商更直观。

经过我的尝试,我发现完全减法会导致超时问题,不得不结合移位操作,代码如下所示:

func divide(dividend int, divisor int) int {
	quotient := 0
	maxInt := math.MaxInt32
	minInt := math.MinInt32
	if divisor == 0 || (dividend == minInt && divisor == -1) {
		return maxInt
	}
	// 确定商的符号
	sign := -1
	if (dividend ^ divisor) >= 0 {
		sign = 1
	}

	// 将被除数和除数转换为正数
	positiveDividend, positiveDivisor := int(math.Abs(float64(dividend))), int(math.Abs(float64(divisor)))

	// 每次被除数减去除数的值
	for positiveDividend >= positiveDivisor {
		// 初始化二分搜索的变量
        tempDivisor := positiveDivisor
        multiple := 1
        
        // 执行类似二分搜索的除法
        for positiveDividend >= (tempDivisor << 1) {
            tempDivisor <<= 1
            multiple <<= 1
        }
        
        // 从被除数中减去除数的倍数
        positiveDividend -= tempDivisor
        // 将倍数加到商中
        quotient += multiple
	}
	return int(math.Min(float64(maxInt), math.Max(float64(sign) * float64(quotient), float64(minInt))))
 }