[算法]不使用*、/、+、-、%操作符求一个数的1/3
来源:互联网 发布:易语言获取js后的源码 编辑:程序博客网 时间:2024/06/13 13:03
问:在不使用*、/、+、-、%操作符的情况下,如何求一个数的1/3?(用C语言实现)
第一种方法:使用位操作符并实现“+”操作
// 替换加法运算符 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 0
第二种方法:
#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; }
第三种方法:
log(pow(exp(number),0.33333333333333333333)) /* :-) */
增强版:
log(pow(exp(number),sin(atan2(1,sqrt(8)))))
第四种方法:
#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; }
第五种方法:使用内联汇编
#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); }
第六种方法:
// 注意: 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; }
0 0
- [算法]不使用*、/、+、-、%操作符求一个数的1/
- 对《不使用*、/、+、-、%操作符求一个数的1/3》中算法的理解
- 不使用*、/、+、-、%操作符求一个数的1/3
- 不使用*、/、+、-、%操作符求一个数的1/3
- 不使用*、/、+、-、%操作符求一个数的1/3
- 不使用*、/、+、-、%操作符求一个数的1/3
- 不使用*、/、+、-、%操作符求一个数的1/3
- 不使用*、/、+、-、%操作符求一个数的1/3
- 1.[算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- ROS机器人小车素材
- UNIX Network Programming笔记之第二章
- HDU 1846 Brave Game
- 一些小技巧
- uva11525 - Permutation 线段树加速康托展开
- [算法]不使用*、/、+、-、%操作符求一个数的1/3
- 一些我推荐的和想上的网络课程
- Linux中常见的文件类型
- excel表格设置之冻结窗口(效果:让整个表格分成几部分,可以让下面的内容滚动显示)
- VirtualBox中安装虚拟机时出错:VT-x features locked or unavailable in MSR,VERR_VMX_MSR_LOCKED_OR_DISABLED
- BeanUtils & 防止页面提交的中文乱码
- Ubuntu 右键打开终端
- 测试代码
- 安装ubuntu 13.04后,无线网卡信号不好