C_and_CPP 板


LINE

※ 引述《CaliforCat (加州猫)》之铭言: : 对一个整数取绝对值 : 如果不用到if-else, for, while, do-while : 可以使用什麽方法 : 我想到的都是会用到上列的限制... : 请前辈指教 谢谢 这题假设照原本的限制 再加上不能用任何relational operator或logical operator 但可以使用bitwise operator 则abs(int)有哪些做法 有放推文的表示概念上是一样我再重新用C实作 ※法1 #include <stdio.h> int main() { unsigned int num; while (scanf("%d", &num) != EOF) { num ^= (num >> (sizeof(num) * 8 - 1)) * ((num & (~num + 1) * (num | (~num + 1))); printf("%d\n", num); } return 0; } 说明: 这只是纯粹0与1的游戏,当正数时XOR的右运算元是0 sizeof(num) * 8 - 1用来找MSB 必用unsigned是因为在右移时不让它补位 ※法2来了
1F:推 CaptainH: a*((a>0)*2-1) 04/07 04:32
#include <stdio.h> int main() { unsigned int num; while (scanf("%d", &num) != EOF) { num *= 1 - 2 * (num >> (sizeof(num) * 8 - 1)); printf("%d\n", num); } return 0; } x86组语如下: mov eax,[num] shr eax,1F add eax,eax mov edx,00000001 sub edx,eax mov eax,[num] imul eax,edx mov [num],eax 说明: 原来这麽根本不必拐弯抹角,用数学关系就能解了zzz果然还是不够 原理就是当num是正数则乘以1,负数则乘以-1,找出用MSB生出1或-1的方法就行了 正数MSB是0,负数MSB是1,於是1-MSB*2就会是我们要的东西 ※法3
2F:推 chubiei: int myabs(int i)04/07 02:09
3F:→ chubiei: {04/07 02:09
4F:→ chubiei: double d = i; unsigned long long *l = &d;04/07 02:10
5F:→ chubiei: *l <<= 1; *l >>= 1;04/07 02:10
6F:→ chubiei: return d;04/07 02:10
7F:→ chubiei: }04/07 02:10
8F:推 chubiei: 上面的假设是int为32 bits, double和unsigned long long04/07 02:17
9F:→ chubiei: 都是64 bits 04/07 02:17
#include <stdio.h> #include <stdint.h> int main() { union db2 { int64_t i; double d; }; int32_t num; db2 tmp; while (scanf("%d", &num) != EOF) { tmp.d = (double)num; tmp.i &= ~(1ull << (sizeof(double) * 8 - 1)); num = (int32_t)tmp.d; printf("%d\n", num); } return 0; } 说明: 有点邪门,先把int转成double,而由於IEEE 754只用MSB控制正负号 於是把负数MSB干掉後这个double就变成正数,再转回int就是绝对值了 至於用union是因为double没有bitwise运算子,必须把它视为整数型别才能做 ※法4 #include <stdio.h> #include <stdlib.h> // int abs(int); int main() { int num; while (scanf("%d", &num) != EOF) printf("%d\n", abs(num)); return 0; } 发现abs只用了三条x86指令就完成了<(_ _)> 然而这是编译器最佳化的结果 当你写(num > 0) ? num : -num就有可能会最佳化成以下这样 mov eax,[num] cdq xor eax,edx sub eax,edx mov [num],eax 说明: 由於cdq在当eax是正数时edx是0,负数则是-1, 正数时和0做XOR此时正数会维持不变,负数时和-1做XOR变成1的补数也就是NOT结果 又在将负数转正数取2的补数时只要NOT後再加一 第三条指令刚好就是减去-1 正数处理时减0维持不变 参考 https://www.strchr.com/optimized_abs_function ※法5 get absolute value without using abs function nor if statement StackOverflow http://stackoverflow.com/questions/9772348/ 底下有一个( n >> 31 | 1 ) * n我竟然没想到要利用补位特性... #include <stdio.h> int main() { int num; while (scanf("%d", &num) != EOF) { printf("%d\n", (num >> (sizeof(int) * 4 - 1) | 1 ) * num); } return 0; } 太神啦 ※法6 开大直接写shellcode Intel Syntax for VC++ int abs(int a) { __asm { mov eax, dword ptr[a] cdq xor eax, edx sub eax, edx } } AT&T Syntax for GCC int abs(int a) { asm ("mov %0, %%eax" :: "r" (a) : "%eax"); asm ("cdq"); asm ("xor %%edx, %%eax" ::: "%eax"); asm ("sub %%edx, %%eax" ::: "%eax"); } -- Sent from my Linux --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 134.208.48.204
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1459961675.A.E21.html
10F:推 Frozenmouse: https://ideone.com/lvKnkB sprintf+sscanf硬干XD 04/07 01:11
11F:→ TobyH4cker: XD 在解一些无脑文字游戏我也都不喜欢用脑直接硬干 04/07 01:16
12F:推 chubiei: int myabs(int i) 04/07 02:09
13F:→ chubiei: { 04/07 02:09
14F:→ chubiei: double d = i; unsigned long long *l = &d; 04/07 02:10
15F:→ chubiei: *l <<= 1; *l >>= 1; 04/07 02:10
16F:→ chubiei: return d; 04/07 02:10
17F:→ chubiei: } 04/07 02:10
18F:推 chubiei: 上面的假设是int为32 bits, double和unsigned long long 04/07 02:17
19F:→ chubiei: 都是64 bits 04/07 02:17
※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 08:34:02
20F:→ TobyH4cker: 这个太邪门啦 04/07 08:35
※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 08:35:50 ※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 09:06:12 ※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 09:54:30 ※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 09:56:02 ※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 10:02:52 ※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 11:03:05 ※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 11:11:41
21F:推 stupid0319: i = i & 0x7FFFFFFF; 这样可以吗? 04/07 11:32
22F:→ TobyH4cker: 不能,负数是以2的补数表示,把整数的MSB抹掉会变别的 04/07 11:39
23F:推 stupid0319: i = i * ((((i>>31) ^ 1) << 1 )- 1); 这样呢 04/07 11:58
24F:→ bibo9901: i = i * (( i>0 ) *2 - 1) 一样啊 04/07 12:03
25F:→ bibo9901: 你还假设int一定要32bit 04/07 12:03
26F:推 stupid0319: 对吼,不知道有没有CPU的指令集比较快 04/07 12:06
27F:→ TobyH4cker: 就是abs 那样已经是最精简的了 04/07 12:17
※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 13:27:01 ※ 编辑: TobyH4cker (134.208.48.204), 04/07/2016 13:58:49
28F:推 tuyutd0505: 推 这篇一堆超狂方法XD 04/07 17:48
29F:推 ronin728: 各种被玩弄的二进制数字与位元运算子XD 04/07 23:04
30F:推 Frozenmouse: wwwww 04/07 23:41
31F:推 wtchen: 以後管版务要来设一个脑筋急转弯专区.... 04/08 01:28
32F:→ Schottky: 我怎觉得像猎奇专区... 04/08 03:05
※ 编辑: TobyH4cker (134.208.48.204), 04/08/2016 11:05:50
33F:推 soheadsome: 算法心得 短码写手表示: 04/08 11:59
34F:推 LiloHuang: v = (v ^ (v >> 31)) - (v >> 31); // int32_t v; 04/08 12:40
35F:→ LiloHuang: 更多 bithacks 技巧以及解说 https://goo.gl/2m2qzH 04/08 12:40
36F:→ BlazarArc: ^看起来有点像在放阿哩固(误 04/08 13:28
37F:→ suhorng: cdq;xor;sub 这个好像是经典作法XD 04/08 19:42
38F:推 Caesar08: 这篇不错 04/10 17:35
39F:推 FukadaKyoko: 应该发文到SO赚点数XD 04/21 10:56







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:WOW站内搜寻

TOP