問:在不使用*、/、+、-、%操做符的狀況下,如何求一個數的1/3?(用C語言實現)git
第一種方法:使用位操做符並實現「+」操做
// 替換加法運算符
int add(int x, int y) {
int a, b;
do {
a = x & y;
b = x ^ y;
x = a << 1;
y = b;
} while (a);
return b;
}
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); i.e. 1, if n == 3, else 0ide
第二種方法:
#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;
函數
} ui
第三種方法:
log(pow(exp(number),0.33333333333333333333)) /* :-) */
加強版:
three
log(pow(exp(number),sin(atan2(1,sqrt(8))))) rem
第四種方法:
#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()是標準C語言函數
printf("%d\n", r.quot);
return 0;
it
} io
第五種方法:使用內聯彙編
#include <stdio.h>
int main() {
int dividend = -42, divisor = 3, quotient, remainder;
__asm__ ( "movl %2, %%edx;"
"sarl $31, %%edx;"
"movl %2, %%eax;"
"movl %3, %%ebx;"
"idivl %%ebx;"
: "=a" (quotient), "=d" (remainder)
: "g" (dividend), "g" (divisor)
: "ebx" );
printf("%i / %i = %i, remainder: %i\n", dividend, divisor, quotient, remainder);
asm
}
第六種方法:
// 注意: itoa 不是個標準函數,但它能夠實現
// 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) str[0] = ' '; // remove sign if positive
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
}
第七種方法:
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++; // 這是++操做符,不是+
floor = r;
r++; // 這也不是
}
return floor;
}
替換掉上面算法的++運算符:
unsigned inc(unsigned x) {
for (unsigned mask = 1; mask; mask <<= 1) {
if (mask & x)
x &= ~mask;
else
return x & mask;
}
return 0; // 溢出(注意:這裏的x和mask都是0)
}
這個版本更快一些:
unsigned add(char const zero[], unsigned const x, unsigned const y) {
// 這是由於:若是foo是char*類型, &foo[bar] == foo+bar
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;
}
第八種方法:實現乘法
int mul(int const x, int const y) {
return sizeof(struct {
char const ignore[y];
}[x]);
}
第九種方法:極限
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 + ...
第十種方法: 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#實現,由於做者更熟悉C#,但本題更傾向於算法,因此語言並非過重要吧?(固然只是在不使用語言特性的前提下。)</stdio.h></stdlib.h></stdio.h></stdlib.h></stdio.h>