{ }codelper

Learn › Python

Going further · 20

Integers and floating point

Why 0.1 + 0.2 isn't 0.3, printing a fixed number of decimals, rounding rules and integer overflow.

Numbers come in two kinds: integers and floating point.
Integers are exact but have limits; floats hold fractions but carry tiny errors.
The example below prints a division to two decimals, then shows truncating, flooring, rounding and adding to a big number.

import math a, b = map(int, input().split())x = float(input())h = float(input())big = int(input()) print(f"{a / b:.2f}")                     # 실수 나눗셈, 소수 둘째 자리s = 0.1 + 0.2                             # 0.30000000000000004print("close" if abs(s - 0.3) < 1e-9 else "far")print(int(x), math.floor(x))              # 버림 -3, 내림 -4print(math.floor(h + 0.5))                # round(2.5)는 2(짝수 쪽)라서 직접print(big + 1)                            # Python 정수는 넘치지 않아요
stdin
2 3
-3.7
2.5
2147483647
stdout
0.67
close
-3 -4
3
2147483648

Key points

  • Integers (int, long) hold whole numbers exactly.
    Floats (double) are stored in binary, so tiny errors creep in.
  • 0.1 + 0.2 is 0.30000000000000004 in every language.
    Every double is the same IEEE 754 double precision, so the error is the same everywhere.
  • Where an exact half (2.5) goes when rounding differs by language.
    There are three rules: to the even neighbour (banker's rounding), toward +∞, or away from zero.
  • Casting a float to an integer drops the fraction toward zero.
    So -3.7 becomes -3, while floor(-3.7), which goes down, is -4.
  • Integers have limits too.
    A 32-bit int tops out at 2147483647 (about 2.1 billion), so bigger values go in a 64-bit integer.

How each language writes it

Pythonf"{x:.2f}" — round(2.5) is 2 (to even).
int(x) truncates.
Integers have no size limit, so they never overflow
JavaScriptx.toFixed(2) — Math.round goes toward +∞ (2.5 → 3, -2.5 → -2); truncate with Math.trunc(x).
There is only one number type (a double), so integers are exact only up to 2^53 (Number.MAX_SAFE_INTEGER); beyond that use BigInt (123n)
TypeScriptSame as JavaScript
JavaString.format("%.2f", x) — Math.round goes toward +∞ (-2.5 → -2).
An overflowing int silently wraps to -2147483648.
Use long for big values
C#x.ToString("F2") — Math.Round(2.5) is 2 (to even); switch with Math.Round(x, MidpointRounding.AwayFromZero).
An overflowing int wraps, or throws OverflowException inside checked
C++std::fixed << std::setprecision(2) — it sticks: later float output on that stream uses it too.
round goes away from zero (-2.5 → -3).
Signed overflow is undefined behaviour, so use long long for big values
Cprintf("%.2f", x) — rounding and overflow as in C++.
long is only 32 bits on Windows, so long long is the safe choice
CraykonStr.Fixed(x, 2) — Mathf.Round goes away from zero (-2.5 → -3).
Mathf.Quot(x, 1) truncates, Mathf.Floor(x) floors.
One number type (a double), so integers are exact only up to 2^53, and there is no BigInt

Common mistakes

Dividing two integers lost the fractionJava · C# · C · C++

int a = 7, b = 2;
double r = a / b;

→ r is 3.0: the integer division happens first, then it becomes a double

Turn one side into a double first: (double)a / b.

The int overflowedJava · C# · C · C++

int n = 2147483647;
n = n + 1;

→ Java and C# give -2147483648 with no error. In C and C++ it is undefined behaviour

Put big values in a long (long long in C/C++).

Craykon prints 0.3Craykon

Console.WriteLine(0.1 + 0.2);
Console.WriteLine(0.1 + 0.2 == 0.3);

→ 0.3 and false — it only rounds at the ninth decimal for display; the value is 0.30000000000000004

Don't trust what is shown; compare by checking the difference is tiny.

How languages differ
Never compare floats with ==.
Check whether the difference is tiny (abs(a - b) < 1e-9), and for values that must be exact, such as money, multiply by 100 and work in whole cents.

Practice