@AlexandreC. - эти методы используют сложение (+), хотя.
топор - сделано с SOverflow
19
Это был оракул, так какие части оракула вам разрешали использовать?
Хоган
8
Идентифицированный дубликат не является дубликатом. Обратите внимание, что в некоторых ответах здесь не используется ни сдвиг битов, ни сложение, поскольку этот вопрос не ограничивал решение этих операций.
Это простая функция, которая выполняет желаемую операцию. Но для этого требуется +оператор, поэтому все, что вам осталось сделать, это добавить значения с помощью битовых операторов:
// replaces the + operatorint 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
Таким образом sum += a, n = a + bи итерация
Когда a == 0 (n < 4), sum += floor(n / 3);т.е. 1,if n == 3, else 0
Это, вероятно, ответ, который ищет Oracle. Он показывает, что вы знаете, как операторы +, -, * и / на самом деле реализованы на CPU: простые побитовые операции.
craig65535
21
Это работает, потому что n = 4a + b, n / 3 = a + (a + b) / 3, поэтому сумма + = a, n = a + b и итерация. Когда a == 0 (n <4), sum + = floor (n / 3); т.е. 1, если n == 3, иначе 0.
Джим Балтер
7
Вот трюк, который я нашел, который дал мне подобное решение. В десятичном виде: 1 / 3 = 0.333333повторяющиеся числа позволяют легко рассчитать, используя a / 3 = a/10*3 + a/100*3 + a/1000*3 + (..). В двоичном коде это почти то же самое 1 / 3 = 0.0101010101 (base 2), что приводит к a / 3 = a/4 + a/16 + a/64 + (..). Разделив на 4, мы получаем сдвиг битов. Последняя проверка на num == 3 необходима, потому что у нас есть только целые числа для работы.
Йорик Сийслинг
4
В базе 4 это становится еще лучше a / 3 = a * 0.111111 (base 4) = a * 4^-1 + a * 4^-2 + a * 4^-3 + (..) = a >> 2 + a >> 4 + a >> 6 + (..). Основание 4 также объясняет, почему только 3 округляется в конце, а 1 и 2 могут быть округлены в меньшую сторону.
Йорик Сейслинг
2
@ while1: это побитовая операция И Кроме того, общеизвестным фактом является то, что для n == 2^kследующего верно:, x % n == x & (n-1)поэтому здесь num & 3используется для выполнения, num % 4пока %не допускается.
@earlNameless: вы не знаете, что они используют внутри, они находятся в черном ящике «определена реализация». Ничто не мешает им просто использовать побитовые операторы; во всяком случае, они находятся вне области моего кода, так что это не моя проблема. :)
Matteo Italia
8
@IvoFlipse от Я могу убрать, вы получаете что-то большое и толкаете это во что-то в три раза меньше, а затем смотрите, как много вписывается. Это примерно треть.
Pureferret
27
попросил лучшего программиста на Си (и самого неуклюжего) в нашей компании объяснить код. после того, как он это сделал, я сказал, что это было довольно изобретательно. Он сказал, что «эта штука не является решением проблемы» и попросил меня покинуть его стол
cvursache
6
@cvursache Я думаю, дело в том, что вопрос настолько умственно отсталый, что ответ отмертвым разрешен. «Лучший программист на Си» в вашей компании «с такой же легкостью мог бы сказать« что dreck - это не (правильный) вопрос ».
JeremyP
17
@ JeremyP: точно. Я хочу сказать, что если бы в реальной жизни мне дали компилятор без поддержки арифметики, единственно разумным было бы попросить лучшего компилятора , потому что работать в таких условиях не имеет никакого смысла. Если бы интервьюер хотел проверить мои знания о том, как реализовать деление с помощью побитовых операций, он мог бы просто сказать об этом и задать это как теоретический вопрос; Такие «трюковые упражнения» просто требуют таких ответов.
@bitmask, математические функции обычно реализуются непосредственно в asm.
SingerOfTheFall
7
я просто набрал его в консоли js, он не работает с номером выше 709 (может быть, это просто моя система) Math.log(Math.pow(Math.exp(709),0.33333333333333333333))иMath.log(Math.pow(Math.exp(709),Math.sin(Math.atan2(1,Math.sqrt(8)))))
Shaheer
208
#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);return0;}
@JeremyP Ваш комментарий не ошибается, если предположить, что ответ не может быть написан на C? В конце концов, вопрос помечен буквой «С».
Сет Карнеги
1
@SethCarnegie Ответ не написан на C, это моя точка зрения. Ассемблер x86 не является частью стандарта.
JeremyP
1
@ JeremyP это правда, но asmдиректива есть. И я хотел бы добавить, что компиляторы C не единственные, у которых есть встроенные ассемблеры, Delphi также имеет это.
Сет Карнеги
7
@SethCarnegie asmДиректива упоминается только в стандарте C99 в Приложении J - общие расширения.
JeremyP
2
Сбой в arm-eabi-gcc.
Дамиан Йеррик
106
Используйте Itoa, чтобы преобразовать в базовую строку 3. Бросьте последний трит и вернитесь к основанию 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 digitreturn strtol(str, NULL,3);// Read back result}
@cshemby Я на самом деле не знал, что itoaможет использовать произвольную базу. Если вы сделаете полную рабочую реализацию с использованием, itoaя буду голосовать.
Мистик
2
Реализация будет содержать /и %... :-)
R .. GitHub STOP HELPING ICE
2
@R .. Так же как и реализация printfдля отображения вашего десятичного результата.
Дамиан Йеррик
57
(примечание: см. Edit 2 ниже для лучшей версии!)
Это не так сложно, как кажется, потому что вы сказали «без использования операторов [..] +[..] ». Смотрите ниже, если вы хотите запретить использование персонажа все вместе.+
unsigned div_by(unsignedconst x,unsignedconst by){unsigned floor =0;for(unsigned cmp =0, r =0; cmp <= x;){for(unsigned i =0; i < by; i++)
cmp++;// that's 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;elsereturn x & mask;}return0;// overflow (note that both x and mask are 0 here)}
Редактирование 2: Немного быстрее версия без использования любого оператора , который содержит +, -, *, /, %символы .
unsigned add(charconst zero[],unsignedconst x,unsignedconst y){// this exploits that &foo[bar] == foo+bar if foo is of type char*return(int)(uintptr_t)(&((&zero[x])[y]));}unsigned div_by(unsignedconst x,unsignedconst 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(intconst x,intconst y){returnsizeof(struct{charconst ignore[y];}[x]);}
Я не уверен, возможно ли строго реализовать соответствующий компилятор C на такой платформе. Возможно, нам придется немного расширить правила, например, интерпретировать «по крайней мере 8 бит» как «способные удерживать по крайней мере целые числа от -128 до +127».
Проблема в том, что у вас нет оператора «сдвиг вправо на 1 место» в Си. >>Оператор - это оператор «деление на 2 ^ n», т.е. он задается в терминах арифметики, а не машинного представления.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
Компьютер Setun не является двоичным в любом смысле этого слова, поэтому набор команд должен быть совершенно другим. Тем не менее, я совсем не знаком с работой этого компьютера, поэтому не могу подтвердить, является ли ответ действительно правильным - но, по крайней мере, имеет смысл - и является ли он весьма оригинальным. +1
Виролино
32
Поскольку это из Oracle, как насчет таблицы поиска предварительно рассчитанных ответов. :-D
publicstaticint div_by_3(long a){
a <<=30;for(int i =2; i <=32; i <<=1){
a = add(a, a >> i);}return(int)(a >>32);}publicstaticlong 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+61011+0110
sum =1011^0110=1101
carry =(1011&0110)<<1=0010<<1=0100Now you recurse!1101+0100
sum =1101^0100=1001
carry =(1101&0100)<<1=0100<<1=1000Again!1001+1000
sum =1001^1000=0001
carry =(1001&1000)<<1=1000<<1=10000One last time!0001+10000
sum =0001^10000=10001=17
carry =(0001&10000)<<1=0Done!
Это просто дополнение, которое ты выучил в детстве!
1111011+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
Предположим, что результат div_by_3(a)= x, тогда x <= floor(f(a, i)) < a / 3. Когда a = 3kмы получим неправильный ответ.
это работает для ввода 3? 1/4, 1/16, ... все возвращают 0 для 3, поэтому будут суммироваться до 0, но 3/3 = 1.
топор - сделано с SOverflow
1
Логика хороша, но реализация проблематична. Последовательное приближение n/3всегда меньше, чем n/3означает, что для любого n=3kрезультата будет k-1вместо k.
Xyand
@Albert, Это был первый подход, который я попробовал, с парой вариантов, но все они потерпели неудачу либо на определенных числах, равномерно делимых на 3, либо на равных делениях на 2 (в зависимости от варианта). Поэтому я попробовал что-то более простое. Я хотел бы увидеть реализацию этого подхода, которая работает, чтобы увидеть, где я облажался.
топор - сделано с SOverflow
@hatchet, вопрос закрыт, поэтому я не могу опубликовать новый ответ, но идея в том, чтобы реализовать бинарный div. Мне должно быть легко найти это.
Это распространенная хитрость компилятора для обхода медленных делений. Но вам, вероятно, нужно сделать некоторые исправления, так как 0x55555556 / 2 ** 32 не совсем 1/3.
CodesInChaos
multiply it, Разве это не означает использование запрещенного *оператора?
luiscubal
8
@luiscubal: Нет, не будет. Вот почему я сказал: «Теперь все, что осталось сделать, это реализовать умножение с использованием битовых операций и сдвигов »
AnT
18
Еще одно решение. Это должно обрабатывать все целые (включая отрицательные), кроме минимального значения типа int, которое должно обрабатываться как жестко закодированное исключение. Это в основном делает деление на вычитание, но только с использованием битовых операторов (сдвиги, xor и & и дополнение). Для более быстрой скорости вычитает 3 * (уменьшая степень 2). В c # он выполняет около 444 этих вызовов DivideBy3 в миллисекунду (2,2 секунды для 1000000 делений), поэтому не ужасающе медленно, но далеко не так быстро, как простой х / 3. Для сравнения, хорошее решение Куди примерно в 5 раз быстрее, чем это.
publicstaticintDivideBy3(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;}publicstaticintNegate(int a){returnAdd(~a,1);}publicstaticintAdd(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 #, потому что это то, что мне пригодилось, но отличия от c должны быть незначительными.
Вам нужно только попытаться вычесть sub один раз, потому что, если бы вы могли вычесть его дважды, вы могли бы вычесть его предыдущей итерации, когда он был вдвое больше, чем сейчас.
Нил
Считается ли (a >= sub)вычитанием?
Нил
@ Нил, я думаю, ты прав. Внутреннее while можно заменить простым if, сохранив ненужное сравнение из второй итерации цикла. Что касается> = вычитания ... Я надеюсь, что нет, потому что это сделало бы это довольно сложно! Я понимаю вашу точку зрения, но думаю, что склонялся бы к той стороне, которая говорит, что> = не считается вычитанием.
топор - сделано с SOverflow
@Neil, я сделал это изменение, которое сократило время вдвое (также спасло ненужные отрицатели).
(Я, конечно, для краткости пропустил некоторые программы.) Если программисту надоело все это печатать, я уверен, что он или она могли бы написать отдельную программу для его генерации. Мне довелось знать об одном операторе /, который значительно упростил бы его работу.
@Enes Unal: не для небольших чисел :) Этот алгоритм очень прост.
ГДж.
Каждый примитивность включает в себя слабые :)
Тоттен
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 enduint32_t y =0;// resultint bit =31;// current bit
printf("X=%u X/3=%u\n",x,x/3);// the '/3' is for testingwhile(bit>0){
printf("BIT=%d X=%u Y=%u\n",bit,x,y);// decrement bitint h =1;while(1){ bit ^= h;if( bit&h ) h <<=1;elsebreak;}uint32_t r = x>>bit;// current remainder in 0..5
x ^= r<<bit;// remove R bits from Xif(r >=3) y |=1<<bit;// new output bit
x |= mod3[r]<<bit;// new remainder inserted in X}
printf("Y=%u\n",y);}
Напишите программу на Паскале и используйте DIVоператор.
Поскольку вопрос помечен свы, вероятно, можете написать функцию на Pascal и вызвать ее из вашей программы на C; метод для этого зависит от системы.
Но вот пример, который работает на моей системе Ubuntu с fp-compilerустановленным пакетом Free Pascal . (Я делаю это из-за неуместного упрямства; я не утверждаю, что это полезно.)
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>externint 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));return0;}
Строить:
fpc divide_by_3.pas && gcc divide_by_3.o main.c -o main
Операторы ++ и - отличаются от операторов + и -! На языке ассемблера есть две инструкции, ADDи INCони не имеют одинаковые коды операций.
Амир Саниян
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);return0;}
Это должно работать для любого делителя, а не только для трех. В настоящее время только для неподписанных, но расширение его до подписанного не должно быть таким сложным.
#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)return0;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);}return0;}
privateint dividedBy3(int n){List<Object> a =newObject[n].ToList();List<Object> b =newList<object>();while(a.Count>2){
a.RemoveRange(0,3);
b.Add(newObject());}return b.Count;}
Потому что они хотят знать, если вы знаете, как процессор работает внутри ... используя математический оператор, в конце концов, выполните операцию, очень похожую на ответ выше.
RaptorX
Или они хотят знать, можете ли вы распознать бесполезную проблему.
Грегуар
1
@Gregoire Я согласен, нет необходимости в такой реализации, но в коммерческой жизни (Orcale) необходимо избегать выполнения бесполезных требований: правильный ответ: «Это вообще не имеет никакого смысла, зачем терять деньги за что? ")
#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);}
Ну, это была просто деталь реализации, поэтому я мог набрать его как 3.0 / 1.0 вместо 0.333333, но я должен играть по правилам. Исправлена!
WJL
Первоначально он был 3.0 / 1.0, что и было в моем тесте. Используя более высокую точность числа, они должны получить достаточно точный результат. gist.github.com/3401496
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))
с у = 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)}
Хотя он использует +, но кто-то уже реализует добавление путем побитовой операции.
Ответы:
Это простая функция, которая выполняет желаемую операцию. Но для этого требуется
+
оператор, поэтому все, что вам осталось сделать, это добавить значения с помощью битовых операторов:Как сказал Джим, это работает, потому что:
n = 4 * a + b
n / 3 = a + (a + b) / 3
Таким образом
sum += a
,n = a + b
и итерацияКогда
a == 0 (n < 4)
,sum += floor(n / 3);
т.е. 1,if n == 3, else 0
источник
1 / 3 = 0.333333
повторяющиеся числа позволяют легко рассчитать, используяa / 3 = a/10*3 + a/100*3 + a/1000*3 + (..)
. В двоичном коде это почти то же самое1 / 3 = 0.0101010101 (base 2)
, что приводит кa / 3 = a/4 + a/16 + a/64 + (..)
. Разделив на 4, мы получаем сдвиг битов. Последняя проверка на num == 3 необходима, потому что у нас есть только целые числа для работы.a / 3 = a * 0.111111 (base 4) = a * 4^-1 + a * 4^-2 + a * 4^-3 + (..) = a >> 2 + a >> 4 + a >> 6 + (..)
. Основание 4 также объясняет, почему только 3 округляется в конце, а 1 и 2 могут быть округлены в меньшую сторону.n == 2^k
следующего верно:,x % n == x & (n-1)
поэтому здесьnum & 3
используется для выполнения,num % 4
пока%
не допускается.Идиотские условия требуют идиотского решения:
Если также требуется десятичная часть, просто объявите
result
какdouble
и добавьте к ней результатfmod(number,divisor)
.Объяснение того, как это работает
fwrite
записиnumber
байт (число является 123456 в примере выше).rewind
сбрасывает указатель файла на начало файла.fread
читает максимумnumber
«записей»divisor
длиной из файла и возвращает количество прочитанных элементов.Если вы записываете 30 байтов, а затем считываете файл в единицах по 3, вы получаете 10 «единиц». 30/3 = 10
источник
источник
Math.log(Math.pow(Math.exp(709),0.33333333333333333333))
иMath.log(Math.pow(Math.exp(709),Math.sin(Math.atan2(1,Math.sqrt(8)))))
источник
Вы можете использовать (в зависимости от платформы) встроенную сборку, например, для x86: (также работает для отрицательных чисел)
источник
asm
директива есть. И я хотел бы добавить, что компиляторы C не единственные, у которых есть встроенные ассемблеры, Delphi также имеет это.asm
Директива упоминается только в стандарте C99 в Приложении J - общие расширения.Используйте Itoa, чтобы преобразовать в базовую строку 3. Бросьте последний трит и вернитесь к основанию 10.
источник
itoa
может использовать произвольную базу. Если вы сделаете полную рабочую реализацию с использованием,itoa
я буду голосовать./
и%
... :-)printf
для отображения вашего десятичного результата.(примечание: см. Edit 2 ниже для лучшей версии!)
Это не так сложно, как кажется, потому что вы сказали «без использования операторов [..]
+
[..] ». Смотрите ниже, если вы хотите запретить использование персонажа все вместе.+
тогда просто скажи
div_by(100,3)
делить100
на3
.Редактировать : Вы можете продолжить и заменить
++
оператора:Редактирование 2: Немного быстрее версия без использования любого оператора , который содержит
+
,-
,*
,/
,%
символы .Мы используем первый аргумент
add
функции, потому что мы не можем обозначать тип указателей без использования*
символа, кроме как в списках параметров функции, где синтаксисtype[]
идентиченtype* const
.FWIW, вы можете легко реализовать функцию умножения, используя подобный прием, чтобы использовать
0x55555556
прием, предложенный AndreyT :источник
++
: почему вы просто не используете/=
?++
это также ярлык: дляnum = num + 1
.+=
это, наконец, сокращениеnum = num + 1
.Это легко возможно на компьютере Setun .
Чтобы разделить целое число на 3, сдвиньте вправо на 1 место .
Я не уверен, возможно ли строго реализовать соответствующий компилятор C на такой платформе. Возможно, нам придется немного расширить правила, например, интерпретировать «по крайней мере 8 бит» как «способные удерживать по крайней мере целые числа от -128 до +127».
источник
>>
Оператор - это оператор «деление на 2 ^ n», т.е. он задается в терминах арифметики, а не машинного представления.Поскольку это из Oracle, как насчет таблицы поиска предварительно рассчитанных ответов. :-D
источник
Вот мое решение:
Во-первых, обратите внимание, что
Теперь все остальное просто!
Теперь все, что нам нужно сделать, это сложить эти сдвинутые по битам значения a! К сожалению! Однако мы не можем добавить, поэтому вместо этого нам нужно написать функцию добавления, используя побитовые операторы! Если вы знакомы с побитовыми операторами, мое решение должно выглядеть довольно просто ... но на случай, если вы не знакомы, в конце я рассмотрю пример.
Еще одна вещь, которую стоит отметить, это то, что сначала я сдвигаюсь влево на 30! Это сделано для того, чтобы дроби не округлялись.
Это просто дополнение, которое ты выучил в детстве!
Эта реализация не удалась, потому что мы не можем добавить все члены уравнения:
Предположим, что результат
div_by_3(a)
= x, тогдаx <= floor(f(a, i)) < a / 3
. Когдаa = 3k
мы получим неправильный ответ.источник
n/3
всегда меньше, чемn/3
означает, что для любогоn=3k
результата будетk-1
вместоk
.Чтобы разделить 32-битное число на 3, можно умножить его на
0x55555556
и затем взять старшие 32 бита 64-битного результата.Теперь осталось только выполнить умножение с использованием битовых операций и сдвигов ...
источник
multiply it
, Разве это не означает использование запрещенного*
оператора?Еще одно решение. Это должно обрабатывать все целые (включая отрицательные), кроме минимального значения типа int, которое должно обрабатываться как жестко закодированное исключение. Это в основном делает деление на вычитание, но только с использованием битовых операторов (сдвиги, xor и & и дополнение). Для более быстрой скорости вычитает 3 * (уменьшая степень 2). В c # он выполняет около 444 этих вызовов DivideBy3 в миллисекунду (2,2 секунды для 1000000 делений), поэтому не ужасающе медленно, но далеко не так быстро, как простой х / 3. Для сравнения, хорошее решение Куди примерно в 5 раз быстрее, чем это.
Это c #, потому что это то, что мне пригодилось, но отличия от c должны быть незначительными.
источник
(a >= sub)
вычитанием?Это действительно довольно легко.
(Я, конечно, для краткости пропустил некоторые программы.) Если программисту надоело все это печатать, я уверен, что он или она могли бы написать отдельную программу для его генерации. Мне довелось знать об одном операторе
/
, который значительно упростил бы его работу.источник
Dictionary<number, number>
вместо повторныхif
утверждений, чтобы иметьO(1)
сложность времени!Использование счетчиков является основным решением:
Также легко выполнить функцию модуля, проверьте комментарии.
источник
Это классический алгоритм деления в базе 2:
источник
Напишите программу на Паскале и используйте
DIV
оператор.Поскольку вопрос помечен свы, вероятно, можете написать функцию на Pascal и вызвать ее из вашей программы на C; метод для этого зависит от системы.
Но вот пример, который работает на моей системе Ubuntu с
fp-compiler
установленным пакетом Free Pascal . (Я делаю это из-за неуместного упрямства; я не утверждаю, что это полезно.)divide_by_3.pas
:main.c
:Строить:
Пример исполнения:
источник
источник
ADD
иINC
они не имеют одинаковые коды операций.Не перепроверять, если этот ответ уже опубликован. Если программа должна быть расширена до плавающих чисел, числа можно умножить на 10 * необходимое количество точности, а затем снова можно применить следующий код.
источник
Это должно работать для любого делителя, а не только для трех. В настоящее время только для неподписанных, но расширение его до подписанного не должно быть таким сложным.
источник
Будет ли обманом использовать
/
оператор "за кулисами", используяeval
конкатенацию строк?Например, в Javacript, вы можете сделать
источник
Использование BC Math в PHP :
MySQL (это интервью от Oracle)
Паскаль :
ассемблер x86-64:
источник
Первое, что я придумал.
РЕДАКТИРОВАТЬ: Извините, я не заметил тег
C
. Но вы можете использовать идею о форматировании строк, я думаю ...источник
Следующий скрипт генерирует программу на C, которая решает проблему без использования операторов
* / + - %
:источник
Использование калькулятора чисел Delight Magic от Hacker's
Где fma - это стандартная библиотечная функция, определенная в
math.h
заголовке.источник
-
ни*
оператор?Как насчет этого подхода (c #)?
источник
Я думаю, что правильный ответ:
Почему бы мне не использовать базовый оператор для выполнения базовой операции?
источник
Решение с использованием библиотечной функции fma () , работает для любого положительного числа:
Смотрите мой другой ответ .
источник
Используйте cblas , входящий в состав OS X Accelerate Framework.
источник
Как правило, решение этого было бы:
log(pow(exp(numerator),pow(denominator,-1)))
источник
Первый:
Затем выясните, как решить x / (1 - y):
с у = 1/4:
Хотя он использует
+
, но кто-то уже реализует добавление путем побитовой операции.источник