I
I
Ivan Yakushenko2019-03-14 20:07:41
Java
Ivan Yakushenko, 2019-03-14 20:07:41

Why is the value of type Long not evaluated?

import java.util.Scanner;

public class LightSpeed {
    public static void main(String[] args) {
        int lightSpeed = 300000;
        long calculatedDistance;
        int runningTime;
        System.out.print("Input days: ");
        Scanner input = new Scanner(System.in);
        runningTime = input.nextInt();
        calculatedDistance = runningTime * 86400 * lightSpeed;
        System.out.println("Light distance: " + calculatedDistance + " km.");
    }
}

If the variable type is runningTime Int, then entering a number greater than 14 will result in an error, because the answer will be outside the range of Int values, but if you change it to Long, then there will be no problem.
Question: in the line calculatedDistance = runningTime * 86400 * lightSpeed; unless the execution will go out of order? That is: assigning the value of the runningTime variable to the calculatedDistance variable, multiplying the number by 86400 and multiplying by lightSpeed? It seems that the operation takes place with the variable runningTime and only then the result is assigned to calculatedDistance.
How do these mathematical operations happen? Are they executed in a variable and then returned to its original value, or are they executed in a buffer? Then why does the buffer have an Int value?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Gornostaev, 2019-03-14
@kshnkvn

There are two interrelated reasons for this behavior. First, the language specification , which standardizes the fact that multiplication of ints produces an int:
After the conversion(s), if any, value set conversion (§5.1.13) is then applied to each operand.
Binary numeric promotion is performed on the operands of certain operators:
Secondly, the principles of operation of stacked virtual machines. This is how the bytecode of the main method looks like:

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=6, args_size=1
         0: ldc           #2   // int 300000
         2: istore_1
         3: getstatic     #3   // Field java/lang/System.out:Ljava/io/PrintStream;
         6: ldc           #4   // String Input days:
         8: invokevirtual #5   // Method java/io/PrintStream.print:(Ljava/lang/String;)V
        11: new           #6   // class java/util/Scanner
        14: dup
        15: getstatic     #7   // Field java/lang/System.in:Ljava/io/InputStream;
        18: invokespecial #8   // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
        21: astore        5
        23: aload         5
        25: invokevirtual #9   // Method java/util/Scanner.nextInt:()I
        28: istore        4
        30: iload         4
        32: ldc           #10  // int 86400
        34: imul
        35: iload_1
        36: imul
        37: i2l
        38: lstore_2
        39: getstatic     #3   // Field java/lang/System.out:Ljava/io/PrintStream;
        42: new           #11  // class java/lang/StringBuilder
        45: dup
        46: invokespecial #12  // Method java/lang/StringBuilder."<init>":()V
        49: ldc           #13  // String Light distance:
        51: invokevirtual #14  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        54: lload_2
        55: invokevirtual #15  // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        58: ldc           #16  // String  km.
        60: invokevirtual #14  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        63: invokevirtual #17  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        66: invokevirtual #18  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        69: return
     LocalVariableTable:
       Start  Length  Slot  Name   Signature
           0      70     0  args   [Ljava/lang/String;
           3      67     1 lightSpeed   I
          39      31     2 calculatedDistance   J
          30      40     4 runningTime   I
          23      47     5 input   Ljava/util/Scanner;

Offsets from the 30th to the 38th are interesting. Two integers are loaded onto the stack, multiplied by the operation imul, as a result of which the original two numbers are removed from the top of the stack and the result of their multiplication is placed, another one is loaded, multiplied again, then the value at the top of the stack is reduced to the longoperation i2land stored in the variable calculatedDistance. Naturally, if the result of the work imulis too large, then an overflow will occur.
Fixing this is easy, just change the type of the constant:
Then the compiler will choose other opcodes that operate on longs:
30: iload         4
32: i2l
33: ldc2_w        #10  // long 86400l
36: lmul
37: iload_1
38: i2l
39: lmul
40: lstore_2

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question