{ }codelper

学习 › C++

基础 · 04

计算和除法

加减乘在各语言中一样,除法却各不相同。

+ - * 在各语言中都一样,但除法和余数(%)各不相同。
下面的例子用两个数依次输出和、差、积、商、余数和小数除法的结果。

#include <iostream> int main() {    int a, b;    std::cin >> a >> b;    std::cout << a + b << '\n';    std::cout << a - b << '\n';    std::cout << a * b << '\n';    std::cout << a / b << '\n';    std::cout << a % b << '\n';    std::cout << (double)a / b << '\n';}
stdin
7 2
stdout
9
5
14
3
1
3.5

要点

  • 有的语言里整数除以整数还是整数:7 / 2 → 3(小数部分被舍去)。
    只有一种数字类型的语言直接得到 3.5。
  • 需要小数结果时,要在除法之前把一边转成浮点数。
  • 遇到负数,语言分成两派:向零截断(-3.5 → -3)和向下取整(-3.5 → -4)。
  • 整数有上限。
    溢出时可能不报错,却得到错误的值。
  • 除以零时,有的语言报错停止,有的语言悄悄得到 Infinity。

各语言的写法

Python// 求商(7 // 2 → 3),/ 总是小数(7 / 2 → 3.5,连 6 / 2 也是 3.0)。
负数向下取整。
整数不会溢出。
除以零报 ZeroDivisionError
JavaScript只有一种数字类型,7 / 2 → 3.5。
求商用 Math.trunc(a / b);Math.floor 对负数结果不同(Math.floor(-3.5) → -4)。
超过 2^53 末尾几位会出错(9007199254740993 → 9007199254740992)。
除以零得到 Infinity
TypeScript和 JavaScript 一样
Java整数 ÷ 整数是整数,要小数用 (double)a / b → 3.5。
向零截断。
int 溢出时不报错,直接绕回。
大数用 long。
整数除以零抛出 ArithmeticException
C#和 Java 一样。
整数除以零抛出 DivideByZeroException
C++整数 ÷ 整数是整数,要小数用 (double)a / b。
向零截断。
有符号整数溢出和除以零都是未定义行为。
大数用 long long
C和 C++ 一样
Craykon只有一种数字类型,7 / 2 → 3.5。
求商用 数学.商(a, b),向下取整用 数学.向下取整。
% 向零截断。
超过 2^53 末尾几位会出错,除以零得到 Infinity

常见错误

除完再转成小数Java · C# · C · C++

int a = 7, b = 2;
double d = (double)(a / b);

→ 3.0 — 括号里的整数除法先算完了

在除法之前转换:(double)a / b → 3.5。

用 x % 2 == 1 找奇数Java · C# · C · C++ · JavaScript · TypeScript · Craykon

int x = -3;
printf("%d\n", x % 2);

→ -1 — 所以 x % 2 == 1 为假,负奇数被漏掉了

写成 x % 2 != 0,在任何语言中都安全。

int 溢出Java · C# · C · C++

int x = 2147483647;
x = x + 1;

→ Java 和 C# 不报错,得到 -2147483648;C 和 C++ 是未定义行为

大数用 long(C 和 C++ 用 long long)。

各语言的差异
负数除法因语言而异。
Python 是 -7 // 2 → -4、-7 % 2 → 1(向下取整);C、C++、Java、C#、JavaScript(Math.trunc)和 Craykon(数学.商)是商 -3、余数 -1(向零截断)。

练习题