Как реализовать беззнаковый 64-битный int в Java с использованием класса BigInteger?

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

Существует класс 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: вопрос, отправленный кем-то здесь, не содержит деталей реализации.

Ответ 1

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

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

Ответ 2

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

Ответ 3

возможно, вам захочется создать класс 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));
    }

    ....
}

Ответ 4

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

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

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

Ответ 5

Вы можете создать BigInteger из long с BigInteger.valueOf(l), где l длинный.

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

Ответ 6

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

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

Использование BigInteger может быть проще, чтобы вы могли обвести голову.;)

Ответ 7

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