负数的整除和余数
刚试了一下负数的整数除法和余数,发现有两种结果。
一种是令余数和被除数的符号一致,例如 C / C++ (网上说还有 java):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main()
{
fprintf(stdout, "(%+d) / (%+d) = %+d; ", x, y, (x) / (y)); \
fprintf(stdout, "(%+d) %% (%+d) = %+d\n", x, y, (x) % (y));
CALC(+5, +2);
CALC(+5, -2);
CALC(-5, +2);
CALC(-5, -2);
return 0;
}
-->
(+5) / (+2) = +2; (+5) % (+2) = +1
(+5) / (-2) = -2; (+5) % (-2) = +1
(-5) / (+2) = -2; (-5) % (+2) = -1
(-5) / (-2) = +2; (-5) % (-2) = -1另一种是令余数和除数的符号一致,例如 python、matlab:
1
2
3
4
5
6
7
8
9
10
11
12def calc(x, y):
print("({:+d}) // ({:+d}) = {:+d}; ({:+d}) % ({:+d}) = {:+d}" \
.format(x, y, (x) // (y), x, y, (x) % (y)))
calc(+5, +2)
calc(+5, -2)
calc(-5, +2)
calc(-5, -2)
-->
(+5) // (+2) = +2; (+5) % (+2) = +1
(+5) // (-2) = -3; (+5) % (-2) = -1
(-5) // (+2) = -3; (-5) % (+2) = +1
(-5) // (-2) = +2; (-5) % (-2) = -1
好吧,知道即可,不纠结。
C++ 原生字符串
引发原生字符串标识提议的是这样一个“惊天地泣鬼神”的例子:
1 | "('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|" |
C++ 整型变量的绝对值
今天在 CppTemplateTutorial 群里面问了一个问题,为什么 C++ 里面的整型绝对值函数 abs
返回有符号类型而不是无符号类型,如 int abs(int)
而不是 unsigned abs(int)
,因为这样会出现 abs(INT_MIN)
不对的情况。后来给出的两个说法比较容易接受:
1 | int b, a; |
不过后来讨论偏了,引来了一个讨论:函数 abs
中是否需要判断?结果还真有这种操作。看 abs
的反汇编,还有 MFC 里面的 abs 实现,都用了下面这种方式(以 int
为例):
1 | int abs(int x) |
第一行的 mask
全部由 x
的符号位组成,对应于正数和负数分别为全 0 (0x00000000
) 和全 1 (0xffffffff
);第二步中的 x ^ mask
,对于正数,仍是 x
,对于负数,结果是 ~x
;第三步的 -mask
,对于正数,因为 mask = 0
所以不变,对于负数,无符号数减去最大的无符号数等于 +1
,即 x - 0xfffffffff = x + 1u
,所以上述函数对于正数等价于 return x
,对于负数等价于 ~(unsigned)(x) + 1u
,在 x != INT_MIN
时正好等价于 (unsigned)(~x) + 1u
,按预期返回。
下面是一个实例代码,用来看各种中间结果。简便起见,这里使用 char
而不是 int
。
1 |
|
下面为当 x
分别取 25 和 -25 时的输出:
1 | x: 19, +025 ux: 19, 025 mask: 00, 000 dx: 19, 025 ddx: 19, 025 ax: 19, +025 |
最后,可以调侃一下。在 C++ 中,对于有符号整型变量 x
,x == (-x)
有两个解:0
和 TYPE_MIN
。