Как реализовать беззнаковое 64-битное int в Java с помощью класса BigInteger? - PullRequest
13 голосов
/ 20 апреля 2009

Я ищу один тип данных с точной емкостью от 0 до 2 ^ 64 - 1. Мы знаем, что Java в том виде, в каком она есть, не поддерживает тип данных типа unsigned.

Существует класс BigInteger, который позволяет создавать большие числа, которые длинный тип данных не может поддерживать. Но я не уверен, как класс BigInteger будет служить моей цели. Класс BigInteger позволяет присваивать только через конструкторы. Я вижу следующую возможность, но она генерирует случайное число.

BigInteger(int numBits, Random rnd) 
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2^numBits - 1), inclusive.

Я не вижу никаких API-интерфейсов setValue (x), которые позволили бы мне выбирать собственное значение для этого BigInteger. Как реализовать это с помощью класса BigInteger или есть ли другой способ сделать это? Пожалуйста, отправьте пример кода.

PS: Вопрос, отправленный кем-то здесь , не содержит подробностей реализации.

Ответы [ 7 ]

6 голосов
/ 20 апреля 2009

Часто вы можете использовать числовые типы данных со знаком Java, как если бы они были без знака.

См. старый ответ о подписанных и неподписанных в Java.

3 голосов
/ 20 апреля 2009

Почему бы не написать свою собственную обертку и использовать подписанную длинную. Если пользователь хочет получить значение без знака как BigInteger - протестируйте знак и добавьте 2 ^ 64 к BigInteger.

2 голосов
/ 20 апреля 2009

вы можете захотеть создать класс UInt64, который инкапсулирует BigInteger; Вы также можете проверить, что каждая операция (add, mul и т. д.) возвращает беззнаковый 64-битный BigInteger; симуляция переполнения может быть хитрой

class UInt64 {

    private final BigInteger value;

    private UInt64(BigInteger aValue) {
         // method to enforce your class invariant: 0...2**64-1
         checkInvariantOf(aValue);
         value = aValue; 
    }

    public static UInt64 of(String value) {
         return new UInt64(new BigInteger(value));
    }

    public UInt64 add(UInt64 v) {
         return new UInt64(value.add(v.value));
    }

    ....
}
2 голосов
/ 20 апреля 2009

Вы можете создать BigInteger из long с помощью BigInteger.valueOf (l), где l - это long.

Но если вы хотите работать с точными 64 битами, я бы использовал просто long.

1 голос
/ 21 августа 2015

В Java SE 8 и более поздних версиях вы можете использовать тип данных long для представления 64-битной длины без знака, которая имеет минимальное значение 0 и максимальное значение 2 ^ 64-1.

1 голос
/ 21 апреля 2009

Вы можете хранить значения от 0 до 2 ^ 64-1 в длинном значении.

Многие операции работают должным образом, однако большинство API и некоторые операции работают только в том случае, если они предполагают подписанные операции, однако существуют обходные пути.

Однако использовать BigInteger может быть проще, чтобы разобраться. ;)

1 голос
/ 20 апреля 2009

BigInteger являются неизменяемыми, как вы уже нашли. Возможно, вы захотите взглянуть на подклассы BigInteger и написать свой собственный конструктор, который проверяет ввод и выдает положительный BigInteger в соответствующем диапазоне.

Чтобы поддерживать требование, что числа используют только 64 бита, вам может потребоваться перегрузить различные операции, чтобы они ограничивали результат и возвращали экземпляр вашего нового класса, а не нового BigInteger.

Это, вероятно, довольно трудоемкая работа, но она все же должна быть намного лучше, чем делать все с нуля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...