杰瑞科技汇

Java中double转int如何避免精度丢失?

Of course! Converting a double to an int in Java is a common task, but it's important to understand the different methods and their implications, especially regarding precision and rounding.

Java中double转int如何避免精度丢失?-图1
(图片来源网络,侵删)

Here’s a complete guide covering the best ways to do it, the pitfalls to avoid, and the reasoning behind each method.


The Short Answer: The Right Way to Cast

The most common and efficient way to convert a double to an int is to use an explicit cast. This method truncates the decimal part, effectively rounding the number towards zero.

double myDouble = 19.95;
int myInt = (int) myDouble;
System.out.println(myInt); // Output: 19

What's happening here? The (int) operator tells the Java compiler to treat the double value as an int. This process involves two steps:

  1. Truncation: The fractional part (.95) is simply discarded.
  2. Assignment: The remaining whole number (19) is stored in the int variable.

Key Methods for Conversion

While casting is the most direct method, other methods exist, each with different behavior. Here are the most important ones:

Java中double转int如何避免精度丢失?-图2
(图片来源网络,侵删)
Method Behavior Example (d = 19.95) Example (d = -19.95) When to Use
(int) d Truncates (rounds towards zero) 19 -19 When you simply want to discard the decimal part. This is the fastest method.
d.intValue() Truncates (rounds towards zero) 19 -19 When you already have a Double object and want to call a method on it.
Math.floor(d) Rounds down (towards negative infinity) 0 -> 19 -20.0 -> -20 When you need to explicitly round down to the nearest integer.
Math.ceil(d) Rounds up (towards positive infinity) 0 -> 20 -19.0 -> -19 When you need to explicitly round up to the nearest integer.
Math.round(d) Rounds to the nearest long 0 -> 20L -20.0 -> -20L When you want standard mathematical rounding (0.5 rounds up). Returns a long.

Detailed Explanation with Code Examples

Let's break down each method with code.

Casting with (int) (Truncation)

This is the go-to method for performance and simplicity when you just want to get rid of the decimal part.

public class DoubleToInt {
    public static void main(String[] args) {
        double positiveDouble = 99.99;
        double negativeDouble = -99.99;
        // Casting truncates the decimal part (rounds towards zero)
        int positiveInt = (int) positiveDouble;
        int negativeInt = (int) negativeDouble;
        System.out.println("Original double: " + positiveDouble);
        System.out.println("After casting to int: " + positiveInt); // Output: 99
        System.out.println("Original double: " + negativeDouble);
        System.out.println("After casting to int: " + negativeInt); // Output: -99
    }
}

Using intValue() (Truncation)

This method is part of the Double wrapper class. It's useful when you have a Double object instead of a primitive double.

public class DoubleToIntWrapper {
    public static void main(String[] args) {
        Double myDoubleObj = 123.45;
        // intValue() is a method of the Double class
        int myInt = myDoubleObj.intValue();
        System.out.println(myInt); // Output: 123
    }
}

Using Math.floor() (Rounding Down)

Math.floor() always rounds to the next lowest integer. You must cast the result to an int because Math.floor() returns a double.

Java中double转int如何避免精度丢失?-图3
(图片来源网络,侵删)
public class DoubleToIntFloor {
    public static void main(String[] args) {
        double value = 9.1;
        double value2 = 9.9;
        double negativeValue = -9.1;
        // Math.floor() rounds DOWN towards negative infinity
        int flooredInt = (int) Math.floor(value);
        int flooredInt2 = (int) Math.floor(value2);
        int flooredNegativeInt = (int) Math.floor(negativeValue);
        System.out.println(Math.floor(9.1)); // Output: 9.0
        System.out.println(flooredInt);      // Output: 9
        System.out.println(Math.floor(9.9)); // Output: 9.0
        System.out.println(flooredInt2);     // Output: 9
        System.out.println(Math.floor(-9.1)); // Output: -10.0
        System.out.println(flooredNegativeInt); // Output: -10
    }
}

Using Math.ceil() (Rounding Up)

Math.ceil() (ceiling) always rounds to the next highest integer. Like floor(), it returns a double, so you need to cast it.

public class DoubleToIntCeil {
    public static void main(String[] args) {
        double value = 9.1;
        double value2 = 9.9;
        double negativeValue = -9.1;
        // Math.ceil() rounds UP towards positive infinity
        int ceiledInt = (int) Math.ceil(value);
        int ceiledInt2 = (int) Math.ceil(value2);
        int ceiledNegativeInt = (int) Math.ceil(negativeValue);
        System.out.println(Math.ceil(9.1)); // Output: 10.0
        System.out.println(ceiledInt);      // Output: 10
        System.out.println(Math.ceil(9.9)); // Output: 10.0
        System.out.println(ceiledInt2);     // Output: 10
        System.out.println(Math.ceil(-9.1)); // Output: -9.0
        System.out.println(ceiledNegativeInt); // Output: -9
    }
}

Using Math.round() (Standard Rounding)

Math.round() performs standard mathematical rounding: if the decimal part is .5 or greater, it rounds up; otherwise, it rounds down.

⚠️ Important: Math.round(double) returns a long, not an int. This is to prevent overflow. You must cast the result to an int.

public class DoubleToIntRound {
    public static void main(String[] args) {
        double value1 = 10.4; // Rounds down
        double value2 = 10.5; // Rounds up
        double value3 = 10.6; // Rounds up
        // Math.round() returns a long, so you must cast to int
        int roundedInt1 = (int) Math.round(value1);
        int roundedInt2 = (int) Math.round(value2);
        int roundedInt3 = (int) Math.round(value3);
        System.out.println(Math.round(10.4)); // Output: 10 (as a long)
        System.out.println(roundedInt1);      // Output: 10
        System.out.println(Math.round(10.5)); // Output: 11 (as a long)
        System.out.println(roundedInt2);      // Output: 11
        System.out.println(Math.round(10.6)); // Output: 11 (as a long)
        System.out.println(roundedInt3);      // Output: 11
    }
}

Important Considerations

Precision and Large Numbers

A double is a 64-bit floating-point number, while an int is a 32-bit integer. This can lead to two issues:

  • Loss of Precision: When a double value is too large to be represented exactly as an int, the conversion will lose precision.
    double largeDouble = 1.23456789012345e30; // A very large number
    int myInt = (int) largeDouble;
    System.out.println(myInt); // Output will be a truncated or incorrect value
  • Overflow: If the double value is outside the range of an int (approx. ±2.1 billion), the result will be incorrect due to integer overflow.
    double overflowDouble = 3.0e10; // 30,000,000,000
    int myInt = (int) overflowDouble;
    System.out.println(myInt); // Output will be not 30 billion, but a truncated value

Rounding vs. Truncation: A Common Pitfall

This is the most important distinction to understand.

Value (int) Value (Truncate) Math.round(value) (Round)
8 9 10
2 9 9
-9.8 -9 -10
-9.2 -9 -9

Choose your method based on the desired outcome. If you're processing currency, Math.round() is usually more accurate. If you're working with coordinates or array indices, truncation might be what you need.

Summary: Which One Should I Use?

  • For simple, fast truncation (discard decimals): Use (int) myDouble.
  • For standard mathematical rounding (e.g., for currency): Use (int) Math.round(myDouble).
  • When you need to explicitly round down: Use (int) Math.floor(myDouble).
  • When you need to explicitly round up: Use (int) Math.ceil(myDouble).
  • When you have a Double object: Use myDoubleObject.intValue().
分享:
扫描分享到社交APP
上一篇
下一篇