Jatin
Jatin

Reputation: 1987

How to multiply LONG and FLOAT in Java

I need to multiply two numbers (for example, A and B) and return the result (A*B).

Condition:

number A: Any number between 0 to Long.MAX_VALUE ( i.e., 0 <= A <= 9,223,372,036,854,775,807)

number B: Any number between 0 to 10000.0000000000) // Remember 'B' will be a decimal number with upto 10 decimal places

If the result of (A * B) contains decimal, then, round up to the next higher integer. for example,

  1. if the result of A x B = 10.1 => 11
  2. if the result of A x B = 10.5 => 11
  3. if the result of A x B = 10.9 => 11
  4. if the result of A x B >= LONG_MAX, then return LONG_MAX (i.e. 9223372036854775807)

I wrote a simple function as mentioned but it is giving me strange result!! Can you please correct me why the function is failing?

static long multiply(long A, float B)
{
    long result = (long) Math.ceil(A * B);
    return result;
}

public static void main(String args[])
{
    System.out.println(multiply(10L, 1.11F)); // 10 x 1.11 => 11.1 => 12 [PASS]
    
    System.out.println(multiply(10L, 1.17F)); //10 x 1.17 => 11.7 => 12 [PASS]
    
    System.out.println(multiply(Long.MAX_VALUE, 1.11F)); // 9223372036854775807 x 1.11 => 9223372036854775807 [PASS]
    
    System.out.println(multiply(9999999L, 9.9999F)); // 9999999 x 9.9999 => 99,998,990.0001 => 99,998,991 [FAIL]
                                                     // I am getting 99998992, instead of 99998991 !!
    
    System.out.println(multiply(4611686018427387908L, 1.0F)); // 4611686018427387908L x 1 => 4611686018427387908 [FAIL]
                                                              // I am getting 4611686018427387904 instead of 4611686018427387908
    
    System.out.println(multiply(96113850L, 1.0F)); // 96113850 x 1 => 96113850 [FAIL]
                                                   // I am getting 96113848 instead of 96113850
}

Last 3 test cases are failing. Please let me know how to correct it?

Thank you.

Upvotes: 1

Views: 712

Answers (2)

slartidan
slartidan

Reputation: 21586

Use BigDecimal to calculate and round in the Decimal number system with almost infinite range:

static long multiply(long A, float B)
{
    return new BigDecimal(A)
           .multiply(new BigDecimal(B))
           .max(new BigDecimal(Long.MAX_VALUE)
           .setScale(0, RoundingMode.UP)
           .longValue();
}

Upvotes: 3

Andreas
Andreas

Reputation: 159114

First, if "'B' will be a decimal number with upto 10 decimal places", then it needs to be a double, not a float.

To prevent loss of precision during the calculation, it needs to be done using BigDecimal.

static long multiply(long a, double b) {
    if (a < 0 || b < 0)
        throw new IllegalArgumentException("Negative value not allowed");
    BigDecimal result = BigDecimal.valueOf(a)
            .multiply(BigDecimal.valueOf(b))
            .setScale(0, RoundingMode.UP);
    return (result.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) < 0
            ? result.longValue() : Long.MAX_VALUE);
}

Test

System.out.println(multiply(10L, 1.11)); // 12
System.out.println(multiply(10L, 1.17)); // 12
System.out.println(multiply(Long.MAX_VALUE, 1.11)); // 9223372036854775807
System.out.println(multiply(9999999L, 9.9999)); // 99998991
System.out.println(multiply(4611686018427387908L, 1.0)); // 4611686018427387908
System.out.println(multiply(96113850L, 1.0)); // 96113850

Upvotes: 5

Related Questions