Разделите число на 3 без использования операторов *, /, +, -,%

643

Как бы вы разделили число на 3 без использования *, /, +, -, %, операторов?

Число может быть подписано или без знака.

  • 2
    Это сложно, так как вы не можете использовать + или - . Вы можете технически реализовать сумматор, используя только логические операторы ...
  • 13
    @AlexandreC. - эти методы используют сложение (+), хотя.
Показать ещё 14 комментариев
Теги:
math
division

48 ответов

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

Это простая функция, которая выполняет желаемую операцию. Но для этого требуется оператор +, поэтому все, что вам осталось сделать, это добавить значения с помощью битовых операторов:

// replaces the + operator
int add(int x, int y)
{
    while (x) {
        int t = (x & y) << 1;
        y ^= x;
        x = t;
    }
    return y;
}

int divideby3 (int num)
{
    int sum = 0;
    while (num > 3) {
        sum = add(num >> 2, sum);
        num = add(num >> 2, num & 3);
    }
    if (num == 3)
        sum = add(sum, 1);
    return sum; 
}

Как Джим прокомментировал это, потому что:

  • n = 4 * a + b
  • n / 3 = a + (a + b) / 3
  • So sum += a, n = a + b, итерация

  • Когда a == 0 (n < 4), sum += floor(n / 3); т.е. 1, if n == 3, else 0

  • 94
    Это, вероятно, ответ, который ищет Oracle. Он показывает, что вы знаете, как операторы +, -, * и / на самом деле реализованы на CPU: простые побитовые операции.
  • 0
    +1, хотя для обработки отрицательных чисел нужна дополнительная логика.
Показать ещё 8 комментариев
425

Идиотические условия требуют идиотского решения:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE * fp=fopen("temp.dat","w+b");
    int number=12346;
    int divisor=3;
    char * buf = calloc(number,1);
    fwrite(buf,number,1,fp);
    rewind(fp);
    int result=fread(buf,divisor,number,fp);
    printf("%d / %d = %d", number, divisor, result);
    free(buf);
    fclose(fp);
    return 0;
}

Если требуется десятичная часть, просто объявите result как double и добавьте к ней результат fmod(number,divisor).

Объяснение того, как это работает

  • fwrite записывает number байты (в примере выше число 123456).
  • rewind сбрасывает указатель файла на переднюю часть файла.
  • fread читает максимум number "записи" длиной divisor в файле и возвращает количество прочитанных элементов.

Если вы пишете 30 байт, тогда прочитайте файл в единицах 3, вы получите 10 "единиц". 30/3 = 10

  • 1
    Мне нравится тот факт, что вызов memset() имеет две (несущественные) ошибки.
  • 2
    @Matteo: я не знаю - я думаю, что это было технически правильно ( memset() который ничего не делает с буфером, которому ничего не нужно делать, это нормально, верно?), И это может помочь интервьюируемому выяснить кое-что о интервьюере.
Показать ещё 20 комментариев
288
log(pow(exp(number),0.33333333333333333333)) /* :-) */
  • 2
    Это может на самом деле работать, если округлено правильно и если число не слишком велико.
  • 249
    Улучшенная версия: log (pow (exp (число), sin (atan2 (1, sqrt (8)))))
Показать ещё 2 комментария
190
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{

    int num = 1234567;
    int den = 3;
    div_t r = div(num,den); // div() is a standard C function.
    printf("%d\n", r.quot);

    return 0;
}
107

Вы можете использовать встроенную сборку (зависимую от платформы), например, для x86: (также работает для отрицательных чисел)

#include <stdio.h>

int main() {
  int dividend = -42, divisor = 5, quotient, remainder;

  __asm__ ( "cdq; idivl %%ebx;"
          : "=a" (quotient), "=d" (remainder)
          : "a"  (dividend), "b"  (divisor)
          : );

  printf("%i / %i = %i, remainder: %i\n", dividend, divisor, quotient, remainder);
  return 0;
}
  • 0
    Это не соответствует предположению, что ответ должен быть написан на C.
  • 2
    @JeremyP Ваш комментарий не ошибается, если предположить, что ответ не может быть написан на C? В конце концов, вопрос помечен буквой «С».
Показать ещё 9 комментариев
100

Используйте itoa для преобразования в базовую строку 3. Снимите последний trit и преобразуйте обратно в базовый 10.

// Note: itoa is non-standard but actual implementations
// don't seem to handle negative when base != 10.
int div3(int i) {
    char str[42];
    sprintf(str, "%d", INT_MIN); // Put minus sign at str[0]
    if (i>0)                     // Remove sign if positive
        str[0] = ' ';
    itoa(abs(i), &str[1], 3);    // Put ternary absolute value starting at str[1]
    str[strlen(&str[1])] = '\0'; // Drop last digit
    return strtol(str, NULL, 3); // Read back result
}
  • 4
    @cshemby Я на самом деле не знал, что itoa может использовать произвольную базу. Если вы сделаете полную рабочую реализацию с использованием itoa я буду голосовать.
  • 2
    Реализация будет содержать / и % ... :-)
Показать ещё 1 комментарий
58

(примечание: см. Редактировать 2 ниже для лучшей версии!)

Это не так сложно, как кажется, потому что вы сказали "без использования операторов [..] + [..] ". См. Ниже, если вы хотите запретить использование символа + все вместе.

unsigned div_by(unsigned const x, unsigned const by) {
  unsigned floor = 0;
  for (unsigned cmp = 0, r = 0; cmp <= x;) {
    for (unsigned i = 0; i < by; i++)
      cmp++; // that not the + operator!
    floor = r;
    r++; // neither is this.
  }
  return floor;
}

то просто скажите div_by(100,3), чтобы разделить 100 на 3.


Изменить. Вы можете продолжить и заменить оператор ++:

unsigned inc(unsigned x) {
  for (unsigned mask = 1; mask; mask <<= 1) {
    if (mask & x)
      x &= ~mask;
    else
      return x & mask;
  }
  return 0; // overflow (note that both x and mask are 0 here)
}

Редактирование 2: Немного более быстрая версия без использования оператора, содержащего символы +, -, *, /, %.

unsigned add(char const zero[], unsigned const x, unsigned const y) {
  // this exploits that &foo[bar] == foo+bar if foo is of type char*
  return (int)(uintptr_t)(&((&zero[x])[y]));
}

unsigned div_by(unsigned const x, unsigned const by) {
  unsigned floor = 0;
  for (unsigned cmp = 0, r = 0; cmp <= x;) {
    cmp = add(0,cmp,by);
    floor = r;
    r = add(0,r,1);
  }
  return floor;
}

Мы используем первый аргумент функции add, потому что мы не можем обозначать тип указателей без использования символа *, за исключением списков параметров функций, где синтаксис type[] идентичен type* const.

FWIW, вы можете легко реализовать функцию умножения, используя аналогичный трюк, чтобы использовать трюк 0x55555556, предложенный AndreyT:

int mul(int const x, int const y) {
  return sizeof(struct {
    char const ignore[y];
  }[x]);
}
  • 2
    Это не похоже на SQL для меня.
  • 5
    Вопрос помечен c , а не SQL, хотя упоминается Oracle.
Показать ещё 10 комментариев
44

Это легко возможно на Setun computer.

Чтобы разделить целое число на 3, сдвинуть вправо на 1 место.

Я не уверен, возможно ли строго реализовать совместимый компилятор C на такой платформе. Возможно, нам придется немного растянуть правила, например, интерпретировать "по меньшей мере 8 бит" как "способных удерживать хотя бы целые числа от -128 до +127".

  • 7
    Проблема в том, что у вас нет оператора «сдвиг вправо на 1 место» в Си. Оператор >> - это оператор «деление на 2 ^ n», т.е. он задается в терминах арифметики, а не машинного представления.
  • 0
    Компьютер Setun не является двоичным в любом смысле этого слова, поэтому набор инструкций должен быть совершенно другим. Тем не менее, я совсем не знаком с работой этого компьютера, поэтому не могу подтвердить, является ли ответ действительно правильным - но, по крайней мере, имеет смысл - и является ли он весьма оригинальным. +1
31

Так как это от Oracle, как насчет таблицы поиска предварительно рассчитанных ответов.:-D

31

Здесь мое решение:

public static int div_by_3(long a) {
    a <<= 30;
    for(int i = 2; i <= 32 ; i <<= 1) {
        a = add(a, a >> i);
    }
    return (int) (a >> 32);
}

public static long add(long a, long b) {
    long carry = (a & b) << 1;
    long sum = (a ^ b);
    return carry == 0 ? sum : add(carry, sum);
}

Во-первых, обратите внимание, что

1/3 = 1/4 + 1/16 + 1/64 + ...

Теперь все просто!

a/3 = a * 1/3  
a/3 = a * (1/4 + 1/16 + 1/64 + ...)
a/3 = a/4 + a/16 + 1/64 + ...
a/3 = a >> 2 + a >> 4 + a >> 6 + ...

Теперь все, что нам нужно сделать, это добавить эти битовые сдвинутые значения a! К сожалению! Однако мы не можем добавить, поэтому вместо этого нам придется писать функцию добавления, используя бит-мудирующие операторы! Если вы знакомы с битовыми операторами, мое решение должно выглядеть довольно простым... но в любом случае вы не будете, я в конце рассмотрю пример.

Еще одна вещь, которую нужно отметить, это то, что сначала я сдвигаюсь налево на 30! Это делается для того, чтобы фракции не округлялись.

11 + 6

1011 + 0110  
sum = 1011 ^ 0110 = 1101  
carry = (1011 & 0110) << 1 = 0010 << 1 = 0100  
Now you recurse!

1101 + 0100  
sum = 1101 ^ 0100 = 1001  
carry = (1101 & 0100) << 1 = 0100 << 1 = 1000  
Again!

1001 + 1000  
sum = 1001 ^ 1000 = 0001  
carry = (1001 & 1000) << 1 = 1000 << 1 = 10000  
One last time!

0001 + 10000
sum = 0001 ^ 10000 = 10001 = 17  
carry = (0001 & 10000) << 1 = 0

Done!

Это просто нести дополнение, которое вы узнали как ребенок!

111
 1011
+0110
-----
10001

Эта реализация не удалась, потому что мы не можем добавить все члены уравнения:

a / 3 = a/4 + a/4^2 + a/4^3 + ... + a/4^i + ... = f(a, i) + a * 1/3 * 1/4^i
f(a, i) = a/4 + a/4^2 + ... + a/4^i

Предположим, что reslut div_by_3(a)= x, тогда x <= floor(f(a, i)) < a / 3. Когда a = 3k, мы получаем неправильный ответ.

  • 2
    это работает для ввода 3? 1/4, 1/16, ... все возвращают 0 для 3, поэтому сумма равна 0, но 3/3 = 1.
  • 1
    Логика хороша, но реализация проблематична. Последовательное приближение n/3 всегда меньше n/3 что означает, что для любого n=3k результат будет k-1 вместо k .
Показать ещё 3 комментария
26

Чтобы разделить 32-разрядное число на 3, можно умножить его на 0x55555556, а затем взять верхние 32 бита результата 64 бит.

Теперь все, что осталось сделать, это реализовать умножение с помощью бит-операций и сдвигов...

  • 1
    Это распространенная хитрость компилятора для обхода медленных делений. Но вам, вероятно, нужно сделать некоторые исправления, так как 0x55555556 / 2 ** 32 не совсем 1/3.
  • 0
    multiply it . Разве это не означает использование запрещенного оператора * ?
Показать ещё 1 комментарий
18

Еще одно решение. Это должно обрабатывать все int (включая отрицательные int), за исключением минимального значения int, которое должно обрабатываться как исключение с жесткой кодировкой. Это в основном деление на вычитание, но только с использованием битовых операторов (сдвиги, xor, и и дополнение). Для более быстрой скорости он вычитает 3 * (уменьшая силу 2). В С# он выполняет около 444 этих вызовов DivideBy3 за миллисекунду (2,2 секунды для 1,000,000 делений), поэтому не ужасающе медленный, но не где почти так же быстро, как простой x/3. Для сравнения, хорошее решение Coodey примерно в 5 раз быстрее, чем это.

public static int DivideBy3(int a) {
    bool negative = a < 0;
    if (negative) a = Negate(a);
    int result;
    int sub = 3 << 29;
    int threes = 1 << 29;
    result = 0;
    while (threes > 0) {
        if (a >= sub) {
            a = Add(a, Negate(sub));
            result = Add(result, threes);
        }
        sub >>= 1;
        threes >>= 1;
    }
    if (negative) result = Negate(result);
    return result;
}
public static int Negate(int a) {
    return Add(~a, 1);
}
public static int Add(int a, int b) {
    int x = 0;
    x = a ^ b;
    while ((a & b) != 0) {
        b = (a & b) << 1;
        a = x;
        x = a ^ b;
    }
    return x;
}

Это С#, потому что это то, что мне было удобно, но отличия от c должны быть незначительными.

  • 0
    Вам нужно всего лишь попытаться вычесть sub один раз, потому что, если бы вы могли вычесть его дважды, вы могли бы вычесть его на предыдущей итерации, когда он был вдвое больше, чем сейчас.
  • 0
    Считает ли (a >= sub) вычитание?
Показать ещё 2 комментария
15

Это очень легко.

if (number == 0) return 0;
if (number == 1) return 0;
if (number == 2) return 0;
if (number == 3) return 1;
if (number == 4) return 1;
if (number == 5) return 1;
if (number == 6) return 2;

(Для краткости я, конечно же, пропустил часть программы.) Если программисту надоело все это печатать, я уверен, что он или она может написать отдельную программу для его создания. Мне известно о каком-то определенном операторе /, что упростило бы его работу.

  • 8
    Вы можете использовать Dictionary<number, number> вместо повторяющихся операторов if так что вы можете иметь O(1) временную сложность!
  • 0
    @PeterOlson это уже O (1) сложность.
Показать ещё 6 комментариев
13

Использование счетчиков является основным решением:

int DivBy3(int num) {
    int result = 0;
    int counter = 0;
    while (1) {
        if (num == counter)       //Modulus 0
            return result;
        counter = abs(~counter);  //++counter

        if (num == counter)       //Modulus 1
            return result;
        counter = abs(~counter);  //++counter

        if (num == counter)       //Modulus 2
            return result;
        counter = abs(~counter);  //++counter

        result = abs(~result);    //++result
    }
}

Также легко выполнить функцию модуля, проверить комментарии.

  • 0
    но это медленно.
  • 0
    @Enes Unal: не для небольших чисел :) Этот алгоритм очень прост.
Показать ещё 1 комментарий
11

Это классический алгоритм деления в базе 2:

#include <stdio.h>
#include <stdint.h>

int main()
{
  uint32_t mod3[6] = { 0,1,2,0,1,2 };
  uint32_t x = 1234567; // number to divide, and remainder at the end
  uint32_t y = 0; // result
  int bit = 31; // current bit
  printf("X=%u   X/3=%u\n",x,x/3); // the '/3' is for testing

  while (bit>0)
  {
    printf("BIT=%d  X=%u  Y=%u\n",bit,x,y);
    // decrement bit
    int h = 1; while (1) { bit ^= h; if ( bit&h ) h <<= 1; else break; }
    uint32_t r = x>>bit;  // current remainder in 0..5
    x ^= r<<bit;          // remove R bits from X
    if (r >= 3) y |= 1<<bit; // new output bit
    x |= mod3[r]<<bit;    // new remainder inserted in X
  }
  printf("Y=%u\n",y);
}
8

Запишите программу в Pascal и используйте оператор DIV.

Так как вопрос помечен c, вы, вероятно, можете написать функцию в Pascal и вызвать ее из своей программы на C; метод для этого является системным.

Но вот пример, который работает на моей системе Ubuntu с установленным пакетом Free Pascal fp-compiler. (Я делаю это из чистого неулокального упрямства, я не утверждаю, что это полезно.)

divide_by_3.pas:

unit Divide_By_3;
interface
    function div_by_3(n: integer): integer; cdecl; export;
implementation
    function div_by_3(n: integer): integer; cdecl;
    begin
        div_by_3 := n div 3;
    end;
end.

main.c:

#include <stdio.h>
#include <stdlib.h>

extern int div_by_3(int n);

int main(void) {
    int n;
    fputs("Enter a number: ", stdout);
    fflush(stdout);
    scanf("%d", &n);
    printf("%d / 3 = %d\n", n, div_by_3(n));
    return 0;
}

Чтобы построить:

fpc divide_by_3.pas && gcc divide_by_3.o main.c -o main

Пример выполнения:

$ ./main
Enter a number: 100
100 / 3 = 33
7

Было бы ошибкой использовать оператор / "за кулисами" с помощью eval и конкатенации строк?

Например, в Javacript вы можете сделать

function div3 (n) {
    var div = String.fromCharCode(47);
    return eval([n, div, 3].join(""));
}
7
int div3(int x)
{
  int reminder = abs(x);
  int result = 0;
  while(reminder >= 3)
  {
     result++;

     reminder--;
     reminder--;
     reminder--;
  }
  return result;
}
  • 0
    Вы использовали оба - и + .... Как это ответ?
  • 3
    Операторы ++ и - отличаются от операторов + и -! На языке ассемблера есть две инструкции ADD и INC чтобы они не имели одинаковые коды операций.
7

Используя BC Math в PHP:

<?php
    $a = 12345;
    $b = bcdiv($a, 3);   
?>

MySQL (это интервью от Oracle)

> SELECT 12345 DIV 3;

Pascal:

a:= 12345;
b:= a div 3;

x86-64 язык ассемблера:

mov  r8, 3
xor  rdx, rdx   
mov  rax, 12345
idiv r8
  • 0
    Классная история, это с тегом C и так было с самого первого дня. Кроме того, вы совершенно не в состоянии понять суть вопроса.
7

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

#include <stdio.h>

unsigned sub(unsigned two, unsigned one);
unsigned bitdiv(unsigned top, unsigned bot);
unsigned sub(unsigned two, unsigned one)
{
unsigned bor;
bor = one;
do      {
        one = ~two & bor;
        two ^= bor;
        bor = one<<1;
        } while (one);
return two;
}

unsigned bitdiv(unsigned top, unsigned bot)
{
unsigned result, shift;

if (!bot || top < bot) return 0;

for(shift=1;top >= (bot<<=1); shift++) {;}
bot >>= 1;

for (result=0; shift--; bot >>= 1 ) {
        result <<=1;
        if (top >= bot) {
                top = sub(top,bot);
                result |= 1;
                }
        }
return result;
}

int main(void)
{
unsigned arg,val;

for (arg=2; arg < 40; arg++) {
        val = bitdiv(arg,3);
        printf("Arg=%u Val=%u\n", arg, val);
        }
return 0;
}
7

Не перекрестно проверять, опубликован ли этот ответ. Если программа должна быть расширена до плавающих чисел, цифры можно умножить на 10 * необходимое количество точности, а затем снова можно применить следующий код.

#include <stdio.h>

int main()
{
    int aNumber = 500;
    int gResult = 0;

    int aLoop = 0;

    int i = 0;
    for(i = 0; i < aNumber; i++)
    {
        if(aLoop == 3)
        {
           gResult++;
           aLoop = 0;
        }  
        aLoop++;
    }

    printf("Reulst of %d / 3 = %d", aNumber, gResult);

    return 0;
}
6

Сначала я придумал.

irb(main):101:0> div3 = -> n { s = '%0' + n.to_s + 's'; (s % '').gsub('   ', ' ').size }
=> #<Proc:0x0000000205ae90@(irb):101 (lambda)>
irb(main):102:0> div3[12]
=> 4
irb(main):103:0> div3[666]
=> 222

EDIT: Извините, я не заметил тег C. Но вы можете использовать идею форматирования строк, я думаю...

5

Следующий script создает C-программу, которая решает проблему без использования операторов * / + - %:

#!/usr/bin/env python3

print('''#include <stdint.h>
#include <stdio.h>
const int32_t div_by_3(const int32_t input)
{
''')

for i in range(-2**31, 2**31):
    print('    if(input == %d) return %d;' % (i, i / 3))


print(r'''
    return 42; // impossible
}
int main()
{
    const int32_t number = 8;
    printf("%d / 3 = %d\n", number, div_by_3(number));
}
''')
5

Использование Калькулятор магов Hacker Delight

int divideByThree(int num)
{
  return (fma(num, 1431655766, 0) >> 32);
}

Где fma - стандартная функция библиотеки, определенная в заголовке math.h.

  • 0
    Как это не использовать оператор - или * ?
  • 0
    Не компилируется как написано ...
4

Думаю, правильный ответ:

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

  • 0
    Потому что они хотят знать, если вы знаете, как процессор работает внутри ... с помощью математического оператора, в конце концов, выполните операцию, очень похожую на ответ выше.
  • 0
    Или они хотят знать, можете ли вы распознать бесполезную проблему.
Показать ещё 1 комментарий
4

Как насчет этого подхода (С#)?

private int dividedBy3(int n) {
        List<Object> a = new Object[n].ToList();
        List<Object> b = new List<object>();
        while (a.Count > 2) {
            a.RemoveRange(0, 3);
            b.Add(new Object());
        }
        return b.Count;
    }
  • 0
    Это помечено C и так было с самого первого дня.
4

Решение, использующее функция fma() библиотеки, работает для любого положительного числа:

#include <stdio.h>
#include <math.h>

int main()
{
    int number = 8;//Any +ve no.
    int temp = 3, result = 0;
    while(temp <= number){
        temp = fma(temp, 1, 3); //fma(a, b, c) is a library function and returns (a*b) + c.
        result = fma(result, 1, 1);
    } 
    printf("\n\n%d divided by 3 = %d\n", number, result);
}

См. мой другой ответ.

  • 0
    Хорошее использование библиотеки. Почему вы не использовали напрямую результат ++?
  • 0
    тогда люди могут сказать, что + был использован.
Показать ещё 1 комментарий
3

первый:

x/3 = (x/4) / (1-1/4)

затем выясните, как решить x/(1 - y):

x/(1-1/y)
  = x * (1+y) / (1-y^2)
  = x * (1+y) * (1+y^2) / (1-y^4)
  = ...
  = x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i)) / (1-y^(2^(i+i))
  = x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i))

с y = 1/4:

int div3(int x) {
    x <<= 6;    // need more precise
    x += x>>2;  // x = x * (1+(1/2)^2)
    x += x>>4;  // x = x * (1+(1/2)^4)
    x += x>>8;  // x = x * (1+(1/2)^8)
    x += x>>16; // x = x * (1+(1/2)^16)
    return (x+1)>>8; // as (1-(1/2)^32) very near 1,
                     // we plus 1 instead of div (1-(1/2)^32)
}

хотя он использует +, но кто-то уже реализует добавление поразрядным op

3

Используйте cblas, включенный как часть OS X Accelerate framework.

[02:31:59] [william@relativity ~]$ cat div3.c
#import <stdio.h>
#import <Accelerate/Accelerate.h>

int main() {
    float multiplicand = 123456.0;
    float multiplier = 0.333333;
    printf("%f * %f == ", multiplicand, multiplier);
    cblas_sscal(1, multiplier, &multiplicand, 1);
    printf("%f\n", multiplicand);
}

[02:32:07] [william@relativity ~]$ clang div3.c -framework Accelerate -o div3 && ./div3
123456.000000 * 0.333333 == 41151.957031
  • 0
    вам не разрешено использовать /
  • 0
    Ну, это была просто деталь реализации, поэтому я мог набрать его как 3.0 / 1.0 вместо 0.333333, но я должен играть по правилам. Исправлена!
Показать ещё 2 комментария
2

Все ответы, вероятно, не то, что любил слушать интервьюер:

Мой ответ:

"Я бы никогда этого не сделал, кто заплатит за такие глупые вещи. будет иметь преимущество в этом, его не быстрее, его только глупо. Дизайнеры-разработчики должны знать это, но это должно работать для всех чисел, а не только для деления на 3"

  • 0
    Что заставляет вас говорить, что интервьюер не хочет этого слышать? Любой кандидат, давший такой ответ на одном из моих собеседований, просто увеличивал свои шансы получить работу. Один здравомыслящий человек в потоке ...
2

Довольно забавный никто не ответил с общим делением:

/* For the given integer find the position of MSB */
int find_msb_loc(unsigned int n)
{
    if (n == 0)
        return 0;

    int loc = sizeof(n)  * 8 - 1;
    while (!(n & (1 << loc)))
        loc--;
    return loc;
}


/* Assume both a and b to be positive, return a/b */
int divide_bitwise(const unsigned int a, const unsigned int b)
{
    int int_size = sizeof(unsigned int) * 8;
    int b_msb_loc = find_msb_loc(b);

    int d = 0; // dividend
    int r = 0; // reminder
    int t_a = a;
    int t_a_msb_loc = find_msb_loc(t_a);
    int t_b = b << (t_a_msb_loc - b_msb_loc);

    int i;
    for(i = t_a_msb_loc; i >= b_msb_loc; i--)  {
        if (t_a > t_b) {
            d = (d << 1) | 0x1;
            t_a -= t_b; // Not a bitwise operatiion
            t_b = t_b >> 1;
         }
        else if (t_a == t_b) {
            d = (d << 1) | 0x1;
            t_a = 0;
        }
        else { // t_a < t_b
            d = d << 1;
            t_b = t_b >> 1;
        }
    }

    r = t_a;
    printf("==> %d %d\n", d, r);
    return d;
}

Побитовое добавление уже дано в одном из ответов, поэтому пропустите его.

2

Хорошо, я думаю, мы все согласны с тем, что это не проблема реального мира. Так что просто для удовольствия, вот как это сделать с Ada и многопоточным:

with Ada.Text_IO;

procedure Divide_By_3 is

   protected type Divisor_Type is
      entry Poke;
      entry Finish;
   private
      entry Release;
      entry Stop_Emptying;
      Emptying : Boolean := False;
   end Divisor_Type;

   protected type Collector_Type is
      entry Poke;
      entry Finish;
   private
      Emptying : Boolean := False;
   end Collector_Type;

   task type Input is
   end Input;
   task type Output is
   end Output;

   protected body Divisor_Type is
      entry Poke when not Emptying and Stop_Emptying'Count = 0 is
      begin
         requeue Release;
      end Poke;
      entry Release when Release'Count >= 3 or Emptying is
         New_Output : access Output;
      begin
         if not Emptying then
            New_Output := new Output;
            Emptying := True;
            requeue Stop_Emptying;
         end if;
      end Release;
      entry Stop_Emptying when Release'Count = 0 is
      begin
         Emptying := False;
      end Stop_Emptying;
      entry Finish when Poke'Count = 0 and Release'Count < 3 is
      begin
         Emptying := True;
         requeue Stop_Emptying;
      end Finish;
   end Divisor_Type;

   protected body Collector_Type is
      entry Poke when Emptying is
      begin
         null;
      end Poke;
      entry Finish when True is
      begin
         Ada.Text_IO.Put_Line (Poke'Count'Img);
         Emptying := True;
      end Finish;
   end Collector_Type;

   Collector : Collector_Type;
   Divisor : Divisor_Type;

   task body Input is
   begin
      Divisor.Poke;
   end Input;

   task body Output is
   begin
      Collector.Poke;
   end Output;

   Cur_Input : access Input;

   -- Input value:
   Number : Integer := 18;
begin
   for I in 1 .. Number loop
      Cur_Input := new Input;
   end loop;
   Divisor.Finish;
   Collector.Finish;
end Divide_By_3;
  • 0
    Это помечено C и так было с самого первого дня. Ваш ответ не по теме.
  • 0
    Выкапывать старые, закрытые вопросы и писать комментарии такого рода. Для нас обоих это пустая трата времени, так как вы должны написать комментарий, и я вижу уведомление, нажимаю на него и нуждаюсь в понимании контекста. Это также не научит меня (я даже не помню, как это писал) и не улучшит ответ (вы на самом деле не думаете, что я переведу это на C, а вы). Чего ты пытаешься достичь?
Показать ещё 4 комментария
1

Если вы напоминаете себе стандартный школьный метод деления и делаете это в двоичном коде, вы обнаружите, что в случае 3 вы только делите и вычитаете ограниченный набор значений (от 0 до 5 в этом случае). Их можно обработать с помощью оператора switch, чтобы избавиться от арифметических операторов.

static unsigned lamediv3(unsigned n)
{
  unsigned result = 0, remainder = 0, mask = 0x80000000;

  // Go through all bits of n from MSB to LSB.
  for (int i = 0; i < 32; i++, mask >>= 1)
  {
    result <<= 1;
    // Shift in the next bit of n into remainder.
    remainder = remainder << 1 | !!(n & mask);

    // Divide remainder by 3, update result and remainer.
    // If remainder is less than 3, it remains intact.
    switch (remainder)
    {
    case 3:
      result |= 1;
      remainder = 0;
      break;

    case 4:
      result |= 1;
      remainder = 1;
      break;

    case 5:
      result |= 1;
      remainder = 2;
      break;
    }
  }

  return result;
}

#include <cstdio>

int main()
{
  // Verify for all possible values of a 32-bit unsigned integer.
  unsigned i = 0;

  do
  {
    unsigned d = lamediv3(i);

    if (i / 3 != d)
    {
      printf("failed for %u: %u != %u\n", i, d, i / 3);
      return 1;
    }
  }
  while (++i != 0);
}
1

Как правило, решением этого будет:

log(pow(exp(numerator),pow(denominator,-1)))

1

Почему бы нам просто не применить определение, изученное в колледже? Результат может быть неэффективным, но ясным, поскольку умножение является просто рекурсивным вычитанием и вычитанием, это дополнение, тогда добавление может быть выполнено с помощью рекурсивной комбинации xor/и логического порта.

#include <stdio.h>

int add(int a, int b){
   int rc;
   int carry;
   rc = a ^ b; 
   carry = (a & b) << 1;
   if (rc & carry) 
      return add(rc, carry);
   else
      return rc ^ carry; 
}

int sub(int a, int b){
   return add(a, add(~b, 1)); 
}

int div( int D, int Q )
{
/* lets do only positive and then
 * add the sign at the end
 * inversion needs to be performed only for +Q/-D or -Q/+D
 */
   int result=0;
   int sign=0;
   if( D < 0 ) {
      D=sub(0,D);
      if( Q<0 )
         Q=sub(0,Q);
      else
         sign=1;
   } else {
      if( Q<0 ) {
         Q=sub(0,Q);
         sign=1;
      } 
   }
   while(D>=Q) {
      D = sub( D, Q );
      result++;
   }
/*
* Apply sign
*/
   if( sign )
      result = sub(0,result);
   return result;
}

int main( int argc, char ** argv ) 
{
    printf( "2 plus 3=%d\n", add(2,3) );
    printf( "22 div 3=%d\n", div(22,3) );
    printf( "-22 div 3=%d\n", div(-22,3) );
    printf( "-22 div -3=%d\n", div(-22,-3) );
    printf( "22 div 03=%d\n", div(22,-3) );
    return 0;
}

Как кто-то говорит... сначала сделайте эту работу. Обратите внимание, что алгоритм должен работать для отрицательного Q...

1
#include <stdio.h>

typedef struct { char a,b,c; } Triple;

unsigned long div3(Triple *v, char *r) {
  if ((long)v <= 2)  
    return (unsigned long)r;
  return div3(&v[-1], &r[1]);
}

int main() {
  unsigned long v = 21; 
  int r = div3((Triple*)v, 0); 
  printf("%ld / 3 = %d\n", v, r); 
  return 0;
}
1

Где InputValue - это число, которое нужно разделить на 3

SELECT AVG(NUM) 
  FROM (SELECT InputValue NUM from sys.dual
         UNION ALL SELECT 0 from sys.dual
         UNION ALL SELECT 0 from sys.dual) divby3
  • 0
    Это помечено C и так было с самого первого дня.
0

Я бы использовал этот код, чтобы разделить все положительные, неплавающие числа. В принципе, вы хотите выровнять биты divisor влево, чтобы соответствовать битам дивидендов. Для каждого сегмента дивиденда (размер делителя), который вы хотите проверить, чтобы убедиться, что сегмент дивидендов больше делителя, тогда вы хотите сдвинуть влево, а затем ИЛИ в первом регистраторе. Эта концепция была первоначально создана в 2004 году (по-моему, standford). Вот версия C, которая использует эту концепцию. Примечание: (я немного изменил его)

int divide(int a, int b)
{
    int c = 0, r = 32, i = 32, p = a + 1;
    unsigned long int d = 0x80000000;

    while ((b & d) == 0)
    {
        d >>= 1;
        r--;
    }

    while (p > a)
    {
        c <<= 1;
        p = (b >> i--) & ((1 << r) - 1);
        if (p >= a)
            c |= 1;
    }
    return c; //p is remainder (for modulus)
}

Пример использования:

int n = divide( 3, 6); //outputs 2
0

Кажется, никто не упомянул критерий деления для 3, представленных в двоичной сумме четных цифр, должен равняться сумме нечетных цифр (аналогично критерию 11 в десятичной форме). Существуют решения, использующие этот трюк под Проверьте, делится ли число на 3.

Я полагаю, что это возможный дубликат, упомянутый Майклом Барром.

0

Ну, вы можете подумать об использовании структуры graph/tree, чтобы решить эту проблему. В основном сгенерируйте столько вершин, сколько числа, которое должно быть разделено на 3. Затем сохраните сопряжение каждой не спаренной вершины с двумя другими вершинами.

Грубый псевдокод:

function divide(int num)
    while(num!=0)
        Add a new vertice to vertiexList.
        num--
    quotient = 0
    for each in vertexList(lets call this vertex A)
        if vertexList not empty
            Add an edge between A and another vertex(say B)
        else
            your Remainder is 1 and Quotient is quotient
        if vertexList not empty
            Add an edge between A and another vertex(say C)
        else
            your remainder is 2 and Quotient is quotient
        quotient++
        remove A, B, C from vertexList
    Remainder is 0 and Quotient is quotient

Это, очевидно, может быть оптимизировано, и сложность зависит от того, насколько велика ваша цифра, но она работает, предоставляя вам возможность делать ++ и -. Это так же хорошо, как подсчет только более холодного.

0

3 в основании 2 равно 11.

Итак, просто сделайте длинное разделение (например, в средней школе) в базе 2 на 11. Это еще проще в базе 2, чем в базе 10.

Для каждой битовой позиции, начинающейся с наиболее значимой:

Решите, если префикс меньше 11.

Если он выводится 0.

Если это не выход 1, а затем замените биты префикса для соответствующего изменения. Есть только три случая:

 11xxx ->    xxx    (ie 3 - 3 = 0)
100xxx ->   1xxx    (ie 4 - 3 = 1)
101xxx ->  10xxx    (ie 5 - 3 = 2)

Все остальные префиксы недоступны.

Повторяйте до минимальной разрядной позиции, и все готово.

0

если мы рассматриваем __div__ не орфографически /

def divBy3(n):
    return n.__div__(3)

print divBy3(9), 'or', 9//3
0

Использование оболочки Linux script:

#include <stdio.h>
int main()
{
    int number = 30;
    char command[25];
    snprintf(command, 25, "echo $((%d %c 3)) ", number, 47);
    system( command );
    return 0;
}

См. мой другой ответ.

0
#!/bin/ruby

def div_by_3(i)
  i.div 3        # always return int http://www.ruby-doc.org/core-1.9.3/Numeric.html#method-i-div
end
  • 0
    ОП попросил решение в С не Ruby
  • 0
    Там не было никакого упоминания о C в вопросе, просто тег. Вы не наняты;)
Показать ещё 1 комментарий
-1

Это сработает...

smegma$ curl http://www.wolframalpha.com/input/?i=14+divided+by+3 2>/dev/null | gawk 'match($0, /link to /input/\?i=([0-9.+-]+)/, ary) { print substr( $0, ary[1, "start"], ary[1, "length"] )}' 4.6666666666666666666666666666666666666666666666666666

Просто замените "14" и "3" на свои номера.

-2

Здесь метод, которым мой дедушка научил меня, когда был ребенком. Он требует операторов + и /, но упрощает расчеты.

Добавьте отдельные цифры вместе, а затем посмотрите, если оно кратно 3.

Но этот метод работает для чисел выше 12.

Пример: 36,

3 + 6 = 9, кратное 3.

42,

4 + 2 = 6, кратное 3.

  • 1
    Как вы определяете, какие цифры без деления на 10? Как вы добавляете их, не используя + ?
  • 1
    Кроме того, это определяет, является ли число кратным 3, но не говорит о том, что вы хотите получить число, кратное. В вашем примере вы не получите 12 или 14.
-2

Хорошо 'ol bc:

$ num=1337; printf "scale=5;${num}\x2F3;\n" | bc
445.66666
-2

Здесь он находится в Python с, в основном, строковыми сравнениями и конечным автоматом.

def divide_by_3(input):
  to_do = {}
  enque_index = 0
  zero_to_9 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  leave_over = 0
  for left_over in (0, 1, 2):
    for digit in zero_to_9:
      # left_over, digit => enque, leave_over
      to_do[(left_over, digit)] = (zero_to_9[enque_index], leave_over)
      if leave_over == 0:
        leave_over = 1
      elif leave_over == 1:
        leave_over = 2
      elif leave_over == 2 and enque_index != 9:
        leave_over = 0
        enque_index = (1, 2, 3, 4, 5, 6, 7, 8, 9)[enque_index]
  answer_q = []
  left_over = 0
  digits = list(str(input))
  if digits[0] == "-":
    answer_q.append("-")
  digits = digits[1:]
  for digit in digits:
    enque, left_over = to_do[(left_over, int(digit))]
    if enque or len(answer_q):
      answer_q.append(enque)
  answer = 0
  if len(answer_q):
    answer = int("".join([str(a) for a in answer_q]))
  return answer

Ещё вопросы

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