C整数除法(不使用乘、除、取余)

文章目录

题目

来源:leetcode =>原题链接
给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 ‘*’、除号 ‘/’ 以及求余符号 ‘%’ 。

注意:

  • 整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
  • 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [ −231 , 231 −1]。本题中,如果除法结果溢出,则返回 231 − 1

示例 1:

输入:a = 15, b = 2
输出:7
解释:15/2 = truncate(7.5) = 7

示例 2:

输入:a = 7, b = -3
输出:-2
解释:7/-3 = truncate(-2.33333…) = -2

提示:

  • -231 <= a, b <= 231 - 1
  • b != 0

思路

整数除法可以当作减法,对于整数a/b的计算,最简单的方法就是定义一个初始变量 res=0 为商,a每减去一个b,res+1,直到 |a|< |b| 为止。

考虑几种特殊情况

  • b != 0
  • a=-231-1, b=-1 时,返回结果正数的最大值 231,防止溢出
  • 符号问题,a b 同号结果为正,a b 异号结果为负
  • 范围问题,正数的范围比负数的范围小,可以把a b全部转成负数计算,标记a b异号情况,最后对结果取负即可

加速计算过程
当除数太小(b=1, b=2),被除数a较大时,减法次数最好越少越好

  • b=1时,res = a
  • b=2时,res=a>>1
    ……(除数不必穷尽列举)
  • 若a能除以2b,则商res也乘2:即res=1,|a| > |b+b|时,a=a-b-b,b=b+b,res=res+res,(b > -230)。这样的商是指数级别的递增

解法

/*
 * 实现32位整数除法运算,不使用/, *, %
 * 只保留除数的整数部分
 * 考虑溢出情况,-2^31-1 ~ 2^31
 *  */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

int divide_neg(int a, int b)
{
	int tmp = a;
	int result = 0;
	while (tmp<=b) {
		int cnt = 1;
		int flag = b;
		/* 加速除的过程,妙 */
		while (flag>-1079741824&&tmp<=(flag+flag)) {
			flag+=flag;
			cnt+=cnt;
			printf("%d flag: %d, cnt: %d\n", __LINE__, flag, cnt);
		}

		tmp -= flag;
		result += cnt;
		printf("%d tmp: %d; result: %d\n", __LINE__, tmp, result);
	}

	return result;
}

int divide(int a, int b){
	int max_value = INT32_MAX;
	int min_value = INT32_MIN;

	int res = 0;
	int sign = -1;

	if (b == 0) {
		printf("divisor value can't be zero\n");
		exit(-1);
	}

	if (a == 0) return 0;
	if (a == min_value && b == -1) return max_value;

	if (b == 1) return a;
	if (b == 2) return  a >> 1; //除数2太小,直接按二进制移位快
	if (b == min_value) return a == min_value? 1:0;//可判可不判

	/* 异号结果为负,标记该情况 */
	if ((a>0 && b<0)||(a<0 && b>0)) sign = 1;

	/* 负数范围比正数大1,全按负负除法计算 */
	if (a>0) a = -a;
	if (b>0) b = -b;

	res = divide_neg(a, b);
	int result = sign == 1?-res:res;

	return result;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值