How to Truncate Decimals in Java (int cast, Math.floor, BigDecimal setScale)

目次

1. What Does “Truncating Decimals” Mean in Java?

When people say “truncate decimals” in Java, they usually mean either removing the fractional part to make an integer or dropping digits after the n-th decimal place.
In real-world code, however, “truncate” can mean more than one thing, so let’s clarify the conclusion first.

1.1 Does “truncate” mean floor? Or cast? (Terminology)

There are mainly two patterns of “truncation.”

  • (A) Truncation toward 0 (truncate)
    Removes the fractional part, but for negative numbers it moves “closer to zero.”
    Examples: 3.9 → 3, -3.9 → -3
    → In Java, (int) casting behaves this way
  • (B) Truncation toward −∞ (floor)
    Moves downward (toward smaller values) on the number line
    Examples: 3.9 → 3, -3.9 → -4
    → In Java, Math.floor() behaves this way

Beginners often get confused because for positive numbers, (A) and (B) produce the same result.
But the moment you handle negative numbers, the results diverge.

1.2 What This Article Helps You Do (Fastest Route by Use Case)

People searching for “java truncate decimals” usually want one of the following.

  • Just convert to an integer (e.g., 3.14 → 3)
    → Casting with (int) is the fastest. But be careful with negative numbers.
  • Truncate at 2 decimal places (e.g., 1.239 → 1.23)
    Math.floor(x * 100) / 100 can work
    → But if precision matters, BigDecimal is safer
  • Money/billing/rates where errors are unacceptable
    → Use BigDecimal + setScale + RoundingMode

If you choose the wrong method, it often “seems to work” but breaks later.
In particular, double-based calculations can introduce precision errors, so for money-related logic it’s safer to design with BigDecimal from the start.

1.3 Common Pitfalls (Fix These First)

Three common mistakes are:

  • Assuming (int) always means floor
    → It actually rounds toward zero, so negative numbers differ.
  • Using Math.floor for truncating decimals, but getting slight mismatches
    → Often caused by double precision (depends on values/environment).
  • Using formatting (DecimalFormat, etc.) as if it changes the computed value
    → The display may change while the internal value stays the same.

First confirm the shortest path: “If you only need an integer, cast.” Then understand the “negative number trap.”

In the next section, we’ll explain truncation via (int) casting with concrete examples.

2. If You Just Want an int, Casting Works (But There’s a Catch)

If you only want to remove the fractional part and get an integer (int), the fastest approach in Java is casting (type conversion).
But casting is not “mathematical truncation (floor).” It’s rounding toward zero (truncate), which matters a lot.

2.1 Basics: Truncate the Fractional Part with (int)

When you convert a double or float to int, the fractional part is dropped.

double x = 3.99;
int a = (int) x;
System.out.println(a); // 3

This is the simplest answer for the common intent “I want to truncate decimals.”

The steps are:

  • Confirm the value is a double / float
  • Add (int) to cast it to int
  • Verify the result—including negative numbers if they can occur

2.2 Important: Casting Rounds Toward Zero (Negative Numbers Differ)

This is the #1 trap for beginners.
Casting does not always “drop to the smaller value.”

System.out.println((int) 3.9);   // 3
System.out.println((int) -3.9);  // -3

-3.9 becoming -3 (not -4) happens because casting converts in the direction closer to zero.

  • 3.9 → 3 (toward zero)
  • -3.9 → -3 (toward zero)

If you want “mathematical truncation (floor),” you need Math.floor(), not casting.
If you miss this, you can get bugs in things like P&L calculations, fee calculations, or coordinate math, where only the negative side is wrong.

2.3 Common Mistakes: Assuming Rounding / Breaking on Negatives

Casting is not rounding-to-nearest.
If you think “0.9 becomes 1,” you’ll get it wrong.

System.out.println((int) 0.9);  // 0
System.out.println((int) 1.9);  // 1

Also, with negative numbers it can feel like the value “increased” or “decreased” unexpectedly.

  • -3.9 → -3 moves in the larger direction on the number line
  • If you expected -4, this is a real bug

Fix is simple:

  • If you only handle positive values → casting is fine
  • If negative values may appear → consider Math.floor()
  • If strict precision is required (money, etc.) → consider BigDecimal

In the next section, we’ll explain Math.floor() / Math.ceil(), which lets you truncate in a mathematically consistent way even for negative numbers.

3. Use Math.floor / Math.ceil for Correct Decimal Truncation

If you want to truncate decimals mathematically correctly, the basic approach is to use Math.floor() instead of casting.
Especially when negative numbers may appear, simply choosing Math.floor() significantly reduces bugs.

3.1 Truncation with Math.floor() (Floor Function)

Math.floor() is called the floor function and rounds values downward (toward smaller values) on the number line.

System.out.println(Math.floor(3.9));   // 3.0
System.out.println(Math.floor(-3.9));  // -4.0

Key points:

  • 3.9 → 3.0 (moves downward)
  • -3.9 → -4.0 (moves further downward)

The biggest advantage is that truncation does not behave unexpectedly with negative numbers.

A common pitfall is that Math.floor() returns a double.
If you need an integer, you must convert it afterward.

3.2 Math.ceil() Rounds Up — Don’t Confuse It

Math.ceil() is the opposite of Math.floor() and rounds upward (toward larger values) on the number line.

System.out.println(Math.ceil(3.1));   // 4.0
System.out.println(Math.ceil(-3.1));  // -3.0

A common mistake is:

  • Thinking “remove decimals” means ceil
    → In reality, ceil rounds up, which is often the opposite of what you want.

If you searched for “truncate decimals,” floor is usually the correct choice.

3.3 Type Conversion When Converting to long / int

If you want to convert the result of Math.floor() to int or long, you need to cast it.

double x = -3.9;

int a = (int) Math.floor(x);
System.out.println(a); // -4

Points to watch:

  • The result of Math.floor() is a double
  • Casting to int removes the decimal part (no mismatch at this stage)
  • If the value is too large, it may not fit into int

For safety, you can choose long first.

double x = 12345678901.9;

long b = (long) Math.floor(x);
System.out.println(b); // 12345678901

Common mistakes include:

  • Forgetting to cast and leaving the value as double
  • Not understanding the difference between floor and casting, causing bugs with negatives
  • Overflow when exceeding the range of int

In short, if negative numbers may be involved, it’s safest to design around Math.floor() from the beginning.

In the next section, we’ll explain how to truncate at the n-th decimal place (for example, keeping two decimals) with concrete examples.

4. How to Truncate at the n-th Decimal Place (Common in Display & Calculations)

In real-world applications, it’s very common to want to keep up to a certain decimal place and drop the rest, not just remove all decimals.
Examples include tax rates, exchange rates, unit prices, and percentages.

Here we organize practical ways to truncate at the n-th decimal place.
When using double, precision issues may occur, so we’ll cover the pitfalls as well.

4.1 Basic Pattern: Multiply by 10^n, floor, then divide

The most common pattern is:

  1. Decide the number of decimal places n
  2. Multiply by 10^n
  3. Apply Math.floor()
  4. Divide by 10^n to restore the scale

For truncating to 2 decimal places (e.g., 1.239 → 1.23):

double x = 1.239;
double y = Math.floor(x * 100) / 100;
System.out.println(y); // 1.23

For truncating to 3 decimal places (e.g., 1.2399 → 1.239):

double x = 1.2399;
double y = Math.floor(x * 1000) / 1000;
System.out.println(y); // 1.239

Advantages of this approach:

  • Short and easy code
  • Uses Math.floor(), so behavior with negative numbers is consistent
  • No additional libraries required

However, because this relies on double, it is not suitable for strict calculations such as money.

4.2 Pitfall: Unexpected Results Due to double Precision

Java’s double is a floating-point type and cannot always represent values like 0.1 or 0.01 exactly.
As a result, you may see seemingly “nonsensical” discrepancies (depending on values and environment).

  • You expect 1.29, but it looks like 1.28
  • You handle 0.3, but internally it’s 0.299999999...

For example, the following code looks logically correct:

double x = 1.29;
double y = Math.floor(x * 100) / 100;
System.out.println(y);

But internally, x * 100 may be represented as 128.999999999....
If floor returns 128, the result becomes 1.28.
This is not a bug in Java, but a property of floating-point arithmetic.

The tricky part is that this happens only occasionally, which makes it hard to catch during testing.

4.3 Safely Truncate with BigDecimal (Recommended)

If you want to truncate at the n-th decimal place reliably, using BigDecimal is the safest choice.
BigDecimal handles base-10 numbers exactly and is commonly used for money calculations.

The basic pattern is:

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN); // truncate at 2 decimal places
System.out.println(y); // 1.23

Key points:

  • setScale(2, ...) keeps two decimal places
  • RoundingMode.DOWN specifies truncation toward zero

Note that BigDecimal’s DOWN is not the same as Math.floor().
With negative numbers, behavior differs, so you may also need to consider FLOOR (explained later).

Common mistakes include:

  • Creating BigDecimal from a double (introducing precision errors)
  • Forgetting to call setScale
  • Using the wrong rounding mode and accidentally rounding half-up

In summary, Math.floor may be enough for display-only purposes, but for important calculations, BigDecimal is the safest choice.

In the next section, we’ll dive deeper into BigDecimal truncation, including the correct way to create instances for real-world code.

5. Truncating with BigDecimal (Safest for Finance, Billing, and Rates)

If you want to truncate decimals with maximum accuracy, BigDecimal should be your first choice in Java.
double is fast but prone to precision errors, which often cause issues later in money, billing, fee, or rate calculations.
BigDecimal handles decimal numbers in a way closer to human expectations, so it’s widely used in business code.

5.1 BigDecimal Basics: Creating from double Is Dangerous (Most Important)

A very common mistake with BigDecimal is how it’s created.
If you pass a double directly, the internal precision error may be preserved.

import java.math.BigDecimal;

BigDecimal a = new BigDecimal(0.1);
System.out.println(a); // May become something like 0.10000000000000000555...

Truncating or calculating with this value often leads to “mysterious” discrepancies.

Safe ways to create BigDecimal are:

(A) Create from a String (most explicit and safe)

BigDecimal a = new BigDecimal("0.1");

(B) Use BigDecimal.valueOf(double) (often recommended)

BigDecimal a = BigDecimal.valueOf(0.1);

For beginners, the safest rule is: when in doubt, create BigDecimal from a String.

5.2 Truncate at n Decimal Places with RoundingMode.DOWN

To truncate at the n-th decimal place, use setScale.

  • setScale(2, ...) → keep two decimal places
  • RoundingMode.DOWN → truncate toward zero
import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("123.4567");
BigDecimal y = x.setScale(2, RoundingMode.DOWN);

System.out.println(y); // 123.45

If you want to drop all decimals and get an integer-like value, the same approach applies.

BigDecimal x = new BigDecimal("123.999");
BigDecimal y = x.setScale(0, RoundingMode.DOWN);

System.out.println(y); // 123

An important detail: setScale changes the value itself, not just how it’s displayed.
This is a calculation operation, not formatting.

5.3 Truncate Toward Zero vs Floor Direction (Important Difference)

BigDecimal offers multiple rounding modes, and there are two that look like “truncation,” which can be confusing.

  • RoundingMode.DOWN: truncate toward zero
    • 3.9 → 3
    • -3.9 → -3
  • RoundingMode.FLOOR: truncate toward −∞ (mathematical floor)
    • 3.9 → 3
    • -3.9 → -4

If you want values to always move toward the smaller side on the number line, FLOOR is the correct choice.

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x1 = new BigDecimal("-3.9");
System.out.println(x1.setScale(0, RoundingMode.DOWN));  // -3
System.out.println(x1.setScale(0, RoundingMode.FLOOR)); // -4

Which one is “correct” depends entirely on your use case.

  • Simply dropping digits (truncate) → DOWN
  • Mathematical truncation (floor) → FLOOR

If this distinction is unclear, negative values can cause serious specification bugs.

5.4 Common BigDecimal Mistakes

Here are frequent mistakes when truncating with BigDecimal:

  • Creating BigDecimal from double and introducing precision errors
    → Avoid new BigDecimal(0.1); use String or valueOf
  • Using the wrong scale
    → For example, using 0 instead of 2 decimal places
  • Mixing up rounding modes
    → Confusing DOWN and FLOOR, causing issues with negative numbers
  • Changing values when you only meant to format
    setScale changes the value; separate calculation and display

In short, for money, billing, or rates—where even a one-cent difference matters—
use BigDecimal and fix both the creation method and rounding mode.

In the next section, we’ll explain how to avoid mixing up display formatting and calculation truncation.

6. DecimalFormat / String.format Are for Display Only (Do Not Use for Calculations)

When truncating decimals, it’s crucial to distinguish whether you want to truncate the calculated value or just format the display.
Mixing these two leads to situations where the screen looks correct but the internal value is wrong, causing bugs later.

The key takeaway: DecimalFormat and String.format are for display only.
If you need to truncate the actual value, use BigDecimal or Math.floor().

6.1 Formatting Decimal Places with DecimalFormat (Truncation Possible)

DecimalFormat is a class for converting numbers into formatted strings.
For example, it’s often used when you want to display two decimal places.

import java.text.DecimalFormat;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(x)); // May become 1.24 (rounded)

What’s important is that the return value of format() is a String,
and the numeric value of x itself does not change.

You can also specify the rounding mode.
To truncate the display, do the following:

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // 1.23

However, this only changes the displayed string; the value of x remains unchanged.

6.2 Caveats When Using String.format

String.format also lets you control numeric output formatting.

double x = 1.239;
System.out.println(String.format("%.2f", x)); // Often rounds to 1.24

In many cases, String.format("%.2f", x) performs round half up behavior.
It’s usually unsuitable if you specifically want truncation.

A very common beginner mistake is converting a formatted string back into a number and using it in calculations.

double x = 1.239;
String s = String.format("%.2f", x); // "1.24"
double y = Double.parseDouble(s);    // 1.24

// At this point, calculations use a rounded value, not a truncated one

This mixes display concerns into calculation logic, making future changes harder.

6.3 Key Pitfall: Correct Display Does Not Mean Correct Values

The most dangerous assumption is “it looks correct on the screen, so it must be fine.”

  • DecimalFormat / String.format change how values look
  • Math.floor / BigDecimal.setScale change the actual value

If you confuse these, you may run into problems like:

  • The UI shows “$1.23” but internal calculations still sum “$1.239”
  • Rounding happens at the wrong stage, causing billing totals to differ
  • Display rounding leaks into calculations, causing audit discrepancies

A simple rule of thumb:

  • Only formatting for display → DecimalFormat (or UI formatting)
  • Truncating as part of calculation → BigDecimal / Math.floor

In the next section, we’ll provide a quick reference table so you can instantly choose the right approach by use case.

7. Best Practices by Use Case (Quick Reference)

“Java decimal truncation” is confusing because there are multiple valid approaches.
Here, we fix the decision by mapping use case → best solution, so you can choose quickly.

7.1 Convert to int (Positive Numbers Only) → Casting Is Enough

If you just want to remove decimals and convert to int, and negative numbers will never appear, casting is the fastest option.

double x = 12.99;
int y = (int) x;
System.out.println(y); // 12

Things to remember:

  • Casting rounds toward zero
  • With positive values, it looks the same as truncation
  • If negatives may appear, don’t lock in this approach

7.2 Truncate Including Negative Numbers → Math.floor

If you want mathematical truncation (floor), Math.floor() is the correct choice.
It’s safer than casting when negative numbers may occur.

double x = -3.9;
int y = (int) Math.floor(x);
System.out.println(y); // -4

Common notes:

  • Math.floor() returns a double
  • Cast to int or long if needed
  • Watch out for int overflow with large values

7.3 Truncate at the n-th Decimal Place (Strict) → BigDecimal + setScale

If you want to truncate at a specific decimal place without precision errors, BigDecimal is the safest option.

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN);

System.out.println(y); // 1.23

This approach is ideal for:

  • Money (JPY, USD, etc.)
  • Billing and tax calculations
  • Rate calculations where errors are unacceptable
  • Batch jobs requiring deterministic results

Common pitfalls:

  • Do not create BigDecimal from double (avoid new BigDecimal(0.1))
  • Understand the difference between DOWN and FLOOR (negative numbers)

7.4 Format for Display Only → DecimalFormat (Never for Calculation)

If you only want to format numbers for display (e.g., two decimals), DecimalFormat is convenient.
However, it does not change the underlying numeric value, so never use it for calculations.

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // "1.23"

Notes:

  • The return value is a String
  • Mixing display logic into calculations causes bugs

In one sentence, the takeaway is:

  • Fast & simple → Casting
  • Correct with negatives → Math.floor
  • Accuracy first (real-world) → BigDecimal
  • Display only → DecimalFormat

Next, we’ll summarize the most common mistakes and how to avoid them.

8. Common Mistakes and Key Warnings

Decimal truncation often “seems to work,” making it easy for beginners to miss subtle bugs.
Here are real-world mistakes and how to avoid them.

8.1 Misunderstanding What “Truncate” Means (Toward 0 vs Floor)

The most common mistake is assuming truncate always means “go smaller.”
In Java, the meaning depends on the method.

  • Casting (int): toward zero
    • 3.9 → 3
    • -3.9 → -3
  • Math.floor(): toward −∞
    • 3.9 → 3
    • -3.9 → -4

If negative values are possible and you use casting, only the negative side will be wrong.
This often goes unnoticed if tests only use positive values.

Countermeasures:

  • If negatives may appear, consider Math.floor() from the start
  • With BigDecimal, don’t confuse RoundingMode.DOWN and FLOOR

8.2 Unexpected Results Due to double Precision

When implementing truncation with Math.floor(x * 100) / 100, you may see mismatches even if the logic looks correct.
The cause is double’s internal representation.

double x = 1.29;
double y = Math.floor(x * 100) / 100;
System.out.println(y);

Depending on the value, x * 100 may become 128.999999999..., resulting in 1.28.
Because this doesn’t happen every time, it’s often discovered in production.

Countermeasures:

  • Use BigDecimal for money and billing
  • If using double, restrict usage to cases where small errors are acceptable

8.3 Using double for Money Calculations

Using double for money often leads to:

  • Totals not matching after truncation
  • Small rounding errors accumulating
  • Mismatch between displayed and internal values

Countermeasures:

  • Use BigDecimal for monetary values
  • Fix the creation method (String or valueOf)
  • Document rounding rules explicitly

8.4 Using Display Formatting for Calculations

Formatting with DecimalFormat or String.format and then parsing back to numbers is dangerous.

double x = 1.239;
String s = String.format("%.2f", x); // display formatting
double y = Double.parseDouble(s);    // used in calculation (dangerous)

This causes:

  • Display rounding leaking into calculations
  • Specification changes affecting logic
  • Loss of separation between display and calculation

Countermeasures:

  • Finish calculations with BigDecimal or Math.floor()
  • Format only at the final display stage
  • Keep calculation and presentation separate

9. Summary: Copy-Paste Conclusions

There are multiple ways to truncate decimals in Java, but the fastest path is to choose by use case.
Here are ready-to-use conclusions.

9.1 If You’re Unsure, Use These

Case 1: Convert to int (Positive Numbers Only)

double x = 12.99;
int y = (int) x;  // 12

Note: With negative numbers, -3.9 → -3, so this is not mathematical floor.

Case 2: Mathematical Truncation Including Negatives

double x = -3.9;
int y = (int) Math.floor(x); // -4

Point: Math.floor() truncates toward −∞.

Case 3: Truncate at n Decimal Places (double, simple)

*Use only when small precision errors are acceptable.

double x = 1.239;
double y = Math.floor(x * 100) / 100; // 1.23

Warning: double precision issues may occur. For strict accuracy, use BigDecimal.

Case 4: Truncate Reliably at n Decimal Places (Recommended)

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN); // 1.23

Key points:

  • Do not create BigDecimal from double
  • Use this for money, billing, and rates

Case 5: Display Only (Never for Calculation)

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // "1.23"

Point: This produces a String; the numeric value is unchanged.

FAQ

Q1. What is the easiest way to truncate decimals in Java?

Answer: If you only need an integer, casting with (int) is the fastest. If negative numbers may appear, consider Math.floor().

Q2. Why does (int) give unexpected results for negative numbers?

Answer: Casting rounds toward zero. For example, -3.9 → -3. For mathematical truncation, use Math.floor().

Q3. How do I truncate to two decimal places (e.g., 1.239 → 1.23)?

Answer: For a simple approach, use Math.floor(x * 100) / 100. For strict accuracy, use BigDecimal.setScale(2, RoundingMode.DOWN).

Q4. Why does Math.floor(x * 100) / 100 sometimes produce wrong values?

Answer: This is due to double precision errors. For money or billing, switch to BigDecimal.

Q5. What is the correct way to truncate using BigDecimal?

Answer: Create BigDecimal from a String or valueOf, then use setScale(n, RoundingMode.DOWN). Avoid new BigDecimal(double).

Q6. What’s the difference between RoundingMode.DOWN and FLOOR?

Answer: They differ for negative numbers. DOWN truncates toward zero; FLOOR truncates toward −∞. Choose based on whether you want truncate or mathematical floor.

Q7. Can I truncate decimals with DecimalFormat?

Answer: You can truncate the display by setting a rounding mode, but it’s for display only. The internal value does not change.

Q8. When should truncation be applied in calculations?

Answer: It depends on the specification. Decide whether to truncate per step or at the end, document the rule clearly, and implement consistently—preferably with BigDecimal.