入门 · 判断

绝对值

绝对值扔掉符号、留下大小。数本身非负就什么都不用做;是负数就翻过来。两种情况,一个分岔 —— 而零必须落在正确的那一边。

一句话答案若 <code>n &lt; 0</code> 就输出 <code>-n</code>,否则输出 <code>n</code>。

题目

输入: 一个整数 n(−1000000 ≤ n ≤ 1000000)。

输出: n 的绝对值。

样例:

输入输出
-77
33

零是真正的边界情况:它的绝对值是 0,不是 −0。条件写成 n < 0(而不是 n <= 0),零就自动落在无害的那一边。

你的解答

main.cpp — 你的解答
「运行我的输入」用的自定义输入

判题在浏览器本地运行。死循环会在 3 秒后被自动中断 —— 但还是确保每个循环都有出口。代码随打随存。

卡住了?提示

提示 1 — 两种情况,不是三种

正数和零的处理一样(原样打印),所以它们合成一个分支。只有负数是特殊的。写三个分支是新手的常见直觉,而且永远多了一个。

提示 2 — 取负就是从零里减

-n 产生相反的值,而不改动 n 本身。想写得更显式,0 - n 是同一件事。两种写法都直接打印结果 —— 别先存回去再打印,那只是多几行。

提示 3 — 为什么不直接调 abs()

可以 —— <cstdlib> 里的 abs() 在这里能用。但这道题要练的是分岔,亲手写一次,那个三行的库函数就不再是魔法。两种都试试,确认结果一致。

题解(先自己试试!)
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    if (n < 0) {
        cout << -n << endl;
    } else {
        cout << n << endl;
    }
    return 0;
}

符号处理到处都有:奇偶统计 里的负余数、整数除法那篇里的负数除法、日期相差几天 里的负数距离。早点对负数分支熟悉起来,后面处处省事。

深度解析

为什么这样做对

绝对值是分两种情况定义的:非负数自己就是自己的大小,负数需要翻符号。只有负数那一支需要分岔,而 -n 能算出翻转结果,又不改动 n 本身。

代价

O(1) —— 一次比较、一次取负。

常见错法

  • 把 n < 0 写成 n <= 0。零照样输出 0,但这个分支现在宣称「零是负数」—— 以后一旦为每支加逻辑,零就落错边了。
  • 写 n = -n 然后在两支里各打印一次,输出重复。在末尾打印一次就好。
  • 以为答案一定装得进 int —— 这里可以,因为输入范围对称。对 -2147483648 就不行,这就是经典的 abs(INT_MIN) 溢出。

下一步

一旦涉及余数,符号处理就更微妙:奇偶统计 和 整数除法那篇。

记住这两句

  • 两种情况就够:负数翻转,其余不动。
  • 用 n < 0 而不是 n <= 0,让零留在无害的那边。
🐞 这段是错的 —— 点开,亲手让它挂一次

只处理了负数分支 —— 非负输入什么都不打印

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    if (n < 0) {
        cout << -n << endl;
    }
    // bug: no else branch, so 0 and positives print nothing
    return 0;
}