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 정수는 넘치지 않아요const lines = require("fs").readFileSync(0, "utf8").trim().split("\n");const [a, b] = lines[0].split(" ").map(Number);const x = Number(lines[1]);const h = Number(lines[2]);const big = Number(lines[3]); console.log((a / b).toFixed(2)); // 수가 하나라 / 는 늘 소수까지const s = 0.1 + 0.2; // 0.30000000000000004console.log(Math.abs(s - 0.3) < 1e-9 ? "close" : "far");console.log(Math.trunc(x), Math.floor(x)); // -3 -4console.log(Math.round(h)); // 2.5 → 3 (단, -2.5 → -2)console.log(big + 1); // 2^53까지는 정확해요import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").trim().split("\n");const [a, b]: number[] = lines[0].split(" ").map(Number);const x: number = Number(lines[1]);const h: number = Number(lines[2]);const big: number = Number(lines[3]); console.log((a / b).toFixed(2)); // 수가 하나라 / 는 늘 소수까지const s: number = 0.1 + 0.2; // 0.30000000000000004console.log(Math.abs(s - 0.3) < 1e-9 ? "close" : "far");console.log(Math.trunc(x), Math.floor(x)); // -3 -4console.log(Math.round(h)); // 2.5 → 3 (단, -2.5 → -2)console.log(big + 1); // 2^53까지는 정확해요import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int a = in.nextInt(), b = in.nextInt(); double x = Double.parseDouble(in.next()); double h = Double.parseDouble(in.next()); int big = in.nextInt(); System.out.println(String.format("%.2f", (double) a / b)); // a / b만 쓰면 0 double s = 0.1 + 0.2; // 0.30000000000000004 System.out.println(Math.abs(s - 0.3) < 1e-9 ? "close" : "far"); System.out.println((int) x + " " + (int) Math.floor(x)); // -3 -4 System.out.println(Math.round(h)); // 2.5 → 3 (long) System.out.println((long) big + 1); // big + 1은 int라 -2147483648 }}using System; class Program{ static void Main() { string[] ab = Console.ReadLine().Split(' '); int a = int.Parse(ab[0]), b = int.Parse(ab[1]); double x = double.Parse(Console.ReadLine()); double h = double.Parse(Console.ReadLine()); int big = int.Parse(Console.ReadLine()); Console.WriteLine(((double)a / b).ToString("F2")); // a / b만 쓰면 0 double s = 0.1 + 0.2; // 0.30000000000000004 Console.WriteLine(Math.Abs(s - 0.3) < 1e-9 ? "close" : "far"); Console.WriteLine($"{(int)x} {Math.Floor(x)}"); // -3 -4 Console.WriteLine(Math.Round(h, MidpointRounding.AwayFromZero)); // 기본은 짝수 쪽(2) Console.WriteLine((long)big + 1); // big + 1은 int라 -2147483648 }}#include <cmath>#include <iomanip>#include <iostream> int main() { int a, b; double x, h; long long big; std::cin >> a >> b >> x >> h >> big; std::cout << std::fixed << std::setprecision(2) << (double)a / b << '\n'; double s = 0.1 + 0.2; // 0.30000000000000004 std::cout << (std::abs(s - 0.3) < 1e-9 ? "close" : "far") << '\n'; std::cout << (int)x << ' ' << (int)std::floor(x) << '\n'; // -3 -4 std::cout << std::llround(h) << '\n'; // 0에서 먼 쪽 → 3 std::cout << big + 1 << '\n'; // int였다면 넘침(정의되지 않은 동작)}#include <stdio.h>#include <math.h> int main(void) { int a, b; double x, h; long long big; scanf("%d %d %lf %lf %lld", &a, &b, &x, &h, &big); printf("%.2f\n", (double)a / b); /* a / b만 쓰면 0 */ double s = 0.1 + 0.2; /* 0.30000000000000004 */ printf("%s\n", fabs(s - 0.3) < 1e-9 ? "close" : "far"); printf("%d %d\n", (int)x, (int)floor(x)); /* -3 -4 */ printf("%.0f\n", round(h)); /* round는 0에서 먼 쪽 */ printf("%lld\n", big + 1); /* int였다면 넘침(정의되지 않은 동작) */ return 0;}ab = Console.ReadNumbers();a = ab[0];b = ab[1];x = Console.ReadLine().ToNumber();h = Console.ReadLine().ToNumber();big = Console.ReadLine().ToNumber(); // / 는 늘 소수까지 나눠요Console.WriteLine(Str.Fixed(a / b, 2));s = 0.1 + 0.2;if (Mathf.Abs(s - 0.3) < 1e-9){ Console.WriteLine("close");}else{ Console.WriteLine("far");}Console.WriteLine(Mathf.Quot(x, 1) + " " + Mathf.Floor(x));Console.WriteLine(Mathf.Round(h));Console.WriteLine(big + 1);2 3 -3.7 2.5 2147483647
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.2is0.30000000000000004in every language.
Everydoubleis 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, whilefloor(-3.7), which goes down, is -4. - Integers have limits too.
A 32-bitinttops out at2147483647(about 2.1 billion), so bigger values go in a 64-bit integer.
How each language writes it
| Python | f"{x:.2f}" — round(2.5) is 2 (to even).int(x) truncates.Integers have no size limit, so they never overflow |
|---|---|
| JavaScript | x.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) |
| TypeScript | Same as JavaScript |
| Java | String.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 |
| C | printf("%.2f", x) — rounding and overflow as in C++.long is only 32 bits on Windows, so long long is the safe choice |
| Craykon | Str.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.
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.