Почему разные выходные значения Java и Python?

Код на Java:
class WTF {
    public static void main(String[] args) {
    	long output_1 = generate(400732734464L, -74, 12);
    	long output_2 = generate(1641401281110016L, 100, 14);

    	System.out.println(String.valueOf(output_1));
    	System.out.println(String.valueOf(output_2));
    }

    public static long generate(long val1, int val2, int val3) {
    	long l;
    	l = val1 + (val2 & 255) << val3;
    	return l;
    }
}

Выводит:
1641401281110016
8445974515998588928


Код на Python:
def generate(val1, val2, val3):
	i = int()
	i = val1 + (val2 & 255) << val3
	return i 

output_1 = generate(400732734464, -74, 12);
output_2 = generate(1641401281110016, 100, 14);

print(output_1)
print(output_2)

Выводит:
1641401281110016
26892718589708140544


Почему разный результат в последних примерах?

UPDATE:
Добавлю ещё php и ruby.
PHP:
$output = 1641401281110016 + (100 & 255) << 14;

echo $output;
//8445974515998588928

Ruby:
output = 1641401281110016 + (100 & 255) << 14;
puts output;
//26892718589708140544

Даже незнаю что и думать )
  • Вопрос задан
  • 521 просмотр
Решения вопроса 1
Vamp
@Vamp
Причина в том, что второй вызов метода вычисляется в значение, не влезающее в тип данных long. То есть возникает классический integer overflow. В java и php старшие биты, не поместившиеся в long, просто отбрасываются. В python и ruby на уровне языка поддерживается bignum арифметика, поэтому результат другой. То есть числа могут быть сколь угодно велики без опасности возникновения переполнения. В php такое тоже возможно при помощи модуля bcmath или gmp. В java аналогичную арифметику предоставляет класс BigInteger:

import java.math.BigInteger;

public class A {
    public static void main(String[] args) {
        BigInteger output_1 = generate(400732734464L, -74, 12);
        BigInteger output_2 = generate(1641401281110016L, 100, 14);

        System.out.println(output_1);
        System.out.println(output_2);
    }

    public static BigInteger generate(long val1, int val2, int val3) {
        return BigInteger.valueOf(val2 & 255)
            .add(BigInteger.valueOf(val1))
            .shiftLeft(val3);
    }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы