关于负数取模与负数除法取整(P1017 进制转化)

首先,除法总是向0取整的,即2/3=0,-2/3还是0,因此可以把负号拿出来变成-(2/3).提取(除数或被除数)负号总是可行的,这还包括-2/-3,2/-3之类的情况.

而负数的取模运算如a%b,标准规定其可由a-(a/b)*b得出,那么可知

  1.运算结果的符号与a相同.    (因为减号右侧的绝对值一定不大于a)

  2.(这意味着)b的符号不影响运算结果.    (把上式中的b换为-b,提取符合后与原式相等)

所以对于涉及负数取模的运算a%b,如果你单纯地想要得到等价的运算结果,可以用这样的方法思考:

  • 用b的绝对值替换b
  • 把a的符号提取出来
  • 进行两正整数之间的取模,并加上a的符号

下面这题中,需要你对负数的取模,整除进行特殊处理,如负数除以负数求正余数,负数除以负数"向下"取整.

 来看看-15转为-2进制的过程.

不停地用-2为除数去除-15,并取余数(正数)为结果中的一位.

-15/-2=7余1,看上去是符合的,然而此时1x(-2)4+1x(-2)3=8,不为7.

当进行正数的进制转化时,每次除总是向下取整取余数为结果,而进行负数的进制转化时,每次除总是向0,也就是向上取整了,我们需要向下取整.

想要这样操作只需要进行一下判断再处理就可以了.

现在,每次除之后想要得到一个正余数,a%b若左侧数为正数,不需要额外处理,如果为负数,写为-b+a%b即可.

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

char num[30] = "0123456789ABCDEFGHIJKLMN";

void slove(int n, int m) {
    if (n > 0 || n % m == 0) {
        slove(n / m, m);
        putchar(num[n % m]);
    } else if (n < 0) {
        slove(n / m + 1, m);
        putchar(num[-m + n % m]);
    }
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    printf("%d=", n);

    slove(n, m);

    printf("(base%d)", m);

    return 0;
}
P1017
原文地址:https://www.cnblogs.com/Gaomez/p/14436408.html