杰瑞科技汇

Java float转long会丢失精度吗?

Of course! Converting a float to a long in Java is a common task, but it's important to understand the nuances to avoid unexpected results.

Java float转long会丢失精度吗?-图1
(图片来源网络,侵删)

Here’s a complete guide covering the different methods, their behavior, and best practices.

The Core Concept: Narrowing and Widening Primitive Conversion

In Java, converting between primitive numeric types has specific rules:

  1. Widening Primitive Conversion: Going from a smaller type to a larger type (e.g., int to double). This is safe and doesn't lose information.
  2. Narrowing Primitive Conversion: Going from a larger type to a smaller type (e.g., double to int). This is not safe and can lead to a loss of precision, data truncation, or overflow.

Since float (32-bit) has a larger range and precision than long (64-bit integer), converting a float to a long is a narrowing primitive conversion. This means Java won't let you do it with a simple cast without an explicit instruction on how to handle the potential data loss.

The conversion process always involves two steps:

Java float转long会丢失精度吗?-图2
(图片来源网络,侵删)
  1. The float value is first converted to a double. This step is exact for most float values.
  2. The resulting double is then converted to a long. This is where the truncation happens: the fractional part is discarded (chopped off), and the number is rounded towards zero.

Method 1: The Explicit Cast (long)

This is the most direct way to perform the conversion. It truncates the decimal part, effectively rounding the number towards zero.

Syntax

long result = (long) myFloatValue;

Behavior

  • Positive Numbers: The decimal part is simply discarded.
    • 99f becomes 123
    • 0f becomes 100
  • Negative Numbers: The decimal part is discarded, moving the number closer to zero.
    • -123.99f becomes -123
    • -100.0f becomes -100
  • Large Values: If the float value is outside the representable range of a long (Long.MIN_VALUE to Long.MAX_VALUE), the result will be the "wrapped-around" long value. For example, a very large positive float will become a negative long.

Example

public class FloatToLongCast {
    public static void main(String[] args) {
        float positiveFloat = 123.78f;
        float negativeFloat = -45.21f;
        float wholeNumberFloat = 99.0f;
        float largeFloat = 3.4028235E38f; // A very large float
        long positiveLong = (long) positiveFloat;
        long negativeLong = (long) negativeFloat;
        long wholeNumberLong = (long) wholeNumberFloat;
        long largeLong = (long) largeFloat;
        System.out.println("Original float: " + positiveFloat + " -> Cast to long: " + positiveLong);
        System.out.println("Original float: " + negativeFloat + " -> Cast to long: " + negativeLong);
        System.out.println("Original float: " + wholeNumberFloat + " -> Cast to long: " + wholeNumberLong);
        System.out.println("Original float: " + largeFloat + " -> Cast to long: " + largeLong);
    }
}

Output:

Original float: 123.78 -> Cast to long: 123
Original float: -45.21 -> Cast to long: -45
Original float: 99.0 -> Cast to long: 99
Original float: 3.4028235E38 -> Cast to long: -9223372036854775808

(Note the last value has overflowed and become Long.MIN_VALUE)


Method 2: Using Math.round()

If you want to round the float to the nearest long instead of truncating, you should use Math.round().

Syntax

long result = Math.round(myFloatValue);

Behavior

  • The value is rounded to the nearest long.
  • If the fractional part is >= 0.5, it rounds up.
  • If the fractional part is < 0.5, it rounds down (towards zero).
  • Return Type: Math.round(float) returns an int. If you need a long, you must cast the result. For double values, it returns a long.

Example

public class FloatToLongRound {
    public static void main(String[] args) {
        float float1 = 123.49f;
        float float2 = 123.50f;
        float float3 = -45.49f;
        float float4 = -45.50f;
        long long1 = Math.round(float1);
        long long2 = Math.round(float2);
        long long3 = Math.round(float3);
        long long4 = Math.round(float4);
        System.out.println("Original float: " + float1 + " -> Rounded to long: " + long1);
        System.out.println("Original float: " + float2 + " -> Rounded to long: " + long2);
        System.out.println("Original float: " + float3 + " -> Rounded to long: " + long3);
        System.out.println("Original float: " + float4 + " -> Rounded to long: " + long4);
    }
}

Output:

Original float: 123.49 -> Rounded to long: 123
Original float: 123.5 -> Rounded to long: 124
Original float: -45.49 -> Rounded to long: -45
Original float: -45.5 -> Rounded to long: -46  // Note: rounds away from zero for .5

Method 3: Using Math.floor() and Math.ceil()

These methods give you more control over the rounding direction.

Math.floor()

Rounds down to the nearest integer (the largest long value less than or equal to the argument).

float myFloat = 123.99f;
long result = (long) Math.floor(myFloat); // Cast is needed because floor returns a double
// result will be 123

Math.ceil()

Rounds up to the nearest integer (the smallest long value greater than or equal to the argument).

float myFloat = 123.01f;
long result = (long) Math.ceil(myFloat); // Cast is needed because ceil returns a double
// result will be 124

Comparison and When to Use Which

Method Syntax Behavior Best For...
Explicit Cast (long) f Truncates (rounds towards zero). Getting the integer part of a number, e.g., for calculations where the decimal is irrelevant.
Math.round() Math.round(f) Rounds to the nearest integer. Standard rounding rules. When you need to round to the nearest whole number, like in financial calculations or statistics.
Math.floor() (long) Math.floor(f) Rounds down (towards negative infinity). When you need the "floor" value, e.g., calculating how many whole items fit into a container.
Math.ceil() (long) Math.ceil(f) Rounds up (towards positive infinity). When you need to "round up" to ensure a minimum value, e.g., calculating how many full boxes you need to ship items.

Important Considerations

  1. Overflow: Be careful with very large float values. A float can represent numbers much larger than Long.MAX_VALUE. Casting such a value to long will result in a wrap-around (overflow) to a negative number.

  2. Special Float Values:

    • Float.NaN (Not a Number): Casting NaN to long results in 0L.
    • Float.POSITIVE_INFINITY: Casting positive infinity to long results in Long.MAX_VALUE.
    • Float.NEGATIVE_INFINITY: Casting negative infinity to long results in Long.MIN_VALUE.
    System.out.println((long) Float.NaN);          // Output: 0
    System.out.println((long) Float.POSITIVE_INFINITY); // Output: 9223372036854775807
    System.out.println((long) Float.NEGATIVE_INFINITY); // Output: -9223372036854775808
分享:
扫描分享到社交APP
上一篇
下一篇