Бинарное дополнение от 0 до 1, от 1 до 0

1

У меня есть число, скажем 4, которое в двоичном выражении представлено как 100, что я хотел бы достичь, это дополнить число, т.е. заменить 1 на 0 и 0 на 1. Я могу добиться этого так

public class Foo {
    public static void main(String[] args) {
        String binaryString = Integer.toBinaryString(4);

        StringBuilder out = new StringBuilder();
        char[] chars = binaryString.toCharArray();
        char x;
        for (char ch : chars) {
            if (ch == '1') {
                x = '0';
            } else {
                x = '1';
            }
            out.append(x);
        }
        System.out.println(Integer.parseInt(out.toString(), 2));
    }
}

Каков наиболее эффективный способ достижения такого же результата с точки зрения временной сложности? Обратите внимание, что ввод может быть очень большим числом, и нам нужно заботиться о переполнении Integer.

Обновленный отказ от числа, такого как ~ n, даст неправильный результат, например

System.out.println(~4); 
outputs -5 , expected 3 
  • 3
    Насколько широкими считаются входные числа? Почему 100 идет на 011 вместо, скажем, 11111011 ? Должно ли 10 идти к 01 или к 101 ?
  • 0
    Кроме того, если входные данные могут быть слишком большими, чтобы поместиться в int, как вы их получаете? Ввод текста на стандартный ввод?
Показать ещё 6 комментариев
Теги:
algorithm

4 ответа

3
Лучший ответ

Каков наиболее эффективный способ достижения такого же результата с точки зрения временной сложности?

Учитывая, что размер int фиксирован на 32, сложность времени равна O (1). Однако ваша программа довольно неэффективна, потому что она создает купе строк, выполняет синтаксический анализ строк и т.д.

Вы можете сделать это быстрее, если вы вообще пропустите преобразование в двоичный код и просто инвертируете число, например:

int val = 4;
int msb = int msb = 32 - Integer.numberOfLeadingZeros(val);
int inverse = ~val & ((1 << msb)-1);
System.out.println(inverse);

Оператор ~ является унарным оператором, который производит двоичное дополнение к значению. Цикл вычисляет положение самого значащего бита (MSB). ((1 << msb)-1) - это маска, которая удаляет все биты выше, чем MSB.

Demo.

  • 0
    обратите внимание, что это также перевернет бит знака, что приведет к -5, а не к 3.
  • 0
    @WoodrowBarlow и этот оператор будет использоваться практически во всех других языках программирования там, где он существует.
Показать ещё 4 комментария
1

Вы можете попробовать использовать побитовое отрицание:

private int flipBits(int n) {
     return ~n;
}
  • 0
    обратите внимание, что это также перевернет бит знака, что приведет к -5, а не к 3.
  • 0
    Это была моя первоначальная попытка, но она также вернет бит знака, например, System.out.println (~ 4); // - 5, ожидается 3
Показать ещё 5 комментариев
1

Почему бы не сделать что-то вроде этого:

public static void main(String[] args) {
        String binaryString = Integer.toBinaryString(4);
        binaryString = binaryString.replaceAll("1", "-");
        binaryString = binaryString.replaceAll("0", "1");
        binaryString = binaryString.replaceAll("-", "0");

Только 3 строки кода для конвертирования...

  • 2
    Три строки кода = три поиска по регулярному выражению, которые намного медленнее, чем простой цикл.
  • 0
    @BackSlash +1 вы попали в точку, вот почему я не использовал replaceAll в моем исходном посте
Показать ещё 1 комментарий
0

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

   //you might want to validate that the string really is a binary number string
    BigInteger myNum = new BigInteger(inputStr, 2);
    BigInteger max = new BigInteger("2");
    max = max.pow(inputStr.length()).subtract(new BigInteger("1"));
    BigInteger ans = max.substract(myNum);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню