Побитовые достигается путем арифметических операций по модулю
- операция Add
Для каждого из них, в случае без учета бит переноса может быть получено
\ [0 + 0 = 0 + 1 = 1 0 \\ \\ \\ 1 + 1 + 0 = 1 1 = 0 \]
Очевидно, что выше при условии исключающее или операции , и только четвёртый случай произошел перенос, перенос, в соответствии с работы. В переносе на всех, должны быть добавлены на более высоком одном месте, это значение может быть влево оперативной реализации. Тогда это может быть
\ [х + у = х \
oplus у + (х \ & у) << 1 \] можно найти за новой формулы в добавили французский, до тех пор , как она может быть рассчитана рекурсивно. Когда \ ((х \ & у) << 1 == 0 \) , французский добавил устранен.
ll add(ll x, ll y) {
ll newx = x^y;
ll newy = (x&y)<<1;
if(newy == 0) return newx;
return add(newx, newy);
}
- вычитание
Операция Вычитание можно рассматривать как
\ [\ BEGIN {выровнен} -y & = \ сим у + 1 \\ х + у & = х + (- у) \\ & = х + \ сим у + 1 \ {конец выровнен} \ ]
также может быть получено путем добавления французского
ll sub(ll x, ll y) {
return add(x, add(~y, 1));
}
- операция умножения
Предположим , что \ (Y = 1010 \) , может быть сосредоточено на бинарных \ (\ 1) битов, то может , (х * у \) \ сделайте разборке
\ [\ {начинают выровненную} х * у = х & * 1010 \\ & = х * 1000
+ X * 0010 \ {конец выровнен} \] , и это только тогда , когда множитель \ (1 \) , то может быть достигнуто с помощью бинарных операций сдвига влево.
ll mul(ll x, ll y) {
ll ans = 0;
int flag = x^y;
x = x<0 ? add(~x, 1) : x;
y = y<0 ? add(~y, 1) : y;
for(int i=0; (1ll<<i)<=y; i++) {
if(y&(1ll<<i)) {
ans = add(ans, x<<i);
}
}
return flag<0 ? add(~ans, 1) : ans;
}
- Отдел операций
И я думал , что один и то же операция умножения, перечислить каждый ответ ли \ (1 \) , чтобы получить продукт, слева и вычитать. Начните с большим начать искать, если есть один \ (1 \) , то этот бит установлен в ответ на \ (1 \) .
ll divide(ll x, ll y) {
ll ans = 0;
int flag = x^y;
x = x<0 ? add(~x, 1) : x;
y = y<0 ? add(~y, 1) : y;
for(int i=31; i>=0; i--) {
if(x >= (1ll*y<<i)) {
ans |= (1ll<<i);
x = sub(x, 1ll*y<<i);
}
}
return flag<0 ? add(~ans, 1) : ans;
}
- операция Modulo
Был результат деления, операция по модулю может быть легко достигнуто
ll mod(ll x, ll y) {
x = x<0 ? add(~x, 1) : x;
y = y<0 ? add(~y, 1) : y;
return sub(x, mul(y, divide(x, y)));
}
Почему объект подкласса может быть присвоен родительский объект, а не наоборот
- Подкласс наследует родительский класс, который содержит часть родительского класса, но также расширение. Если объект дочернего класса присваивается переменным родительский класс, переменный может быть доступно только с использованием класса части подкласса.
- Если, в свою очередь, если эта переменная подкласс для доступа к переменным-членам расширения, вы не посетить, в результате чего памяти из диапазона.