duangsuse::Echo
583 subscribers
4.12K photos
118 videos
579 files
6.13K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
duangsuse::Echo
要是能不要做这种事情,就会省时间。
#Sp #C 汇编害死人! 😢 早日拒绝汇编和 C 甚至裸的结构化编程,早日获得新生! C++ 都比 C 好!

🌶🐔 垃圾 GCC 还我青春!

🤔 C++ 要学呢,类型系统比 C 强一些,新的 cast 操作不知道怎么用。

人在做,天在看,抽象不够留祸患,
万恶段错天地灭,赶紧 OO 保平安,
诚心诚念设模好,对象大法平安保,
众生都为速度来,现世险恶忘前缘,
OO 弟子说真相,教你脱险莫拒绝,
早日摆脱汇编,早日获得新生,
上网搜索「九评 GAS」有真相。

天灭 GCC,退 C 保平安。
人在做,天在看,垃圾 SP 留隐患。
空指溢出天地灭,快换 Managed 保平安。
诚心诚念 GC 好,Tracing 大法平安保。
众生都为工效来,现世险恶忘前缘。
Java 菜鸡说真相,教你脱险莫拒绝,
早日摆脱 C/C++,早日获得新生,
上网搜索「九评 C/C++ 后端」有真相。
duangsuse::Echo
知识星球... 我不知道向不向平台外开放(真正符合 WWW 的概念) 不过我在百度找到了 drakeet 之前的个人博客,现在没被删,当然你们不用通知他去删掉了,如果删了比较可惜,我可懒得再搞事,而且有些东西删了,以后我要重写记起来困难 OutOfMemeory 博客 http://ju.outofmemory.cn/feed/2166/ 这个内容比较多,都是 Android 开发的内容 CSDN 博客 https://blog.csdn.net/drakeet 这个没内容,基本是转载,drakeet…
#bin 然后为了证明我不比 drakeet 差,只是缺少拿来实践的时间, 我分析一下这篇文章《5分钟学会十进制转换成二进制的快速口算方法 & Java输出二进制的代码》,然后就睡觉。

当然,至于 Android 那一套,比如异步、Timer、MessageDriven、Android XML、Android Widgets、Resources、Android Gradle Build 集成、库打包、封装、Android Layouts、Views、Paint、Android Layout Animations、组件化、接口、持久化、SQLite、HTTP、Reactive、Activities 和之间的信息传递、Android IPC、MVP、Databinding、List model view、多线程等套路,还有平常的编程技巧,诸如 Annotation 什么的,都是次要,反正你们记得我被 drakeet 喷了而且看他那个反应很不爽就是了。我就是这性子。而我就自负地觉得我能比他会得多。 😝
虽然我不能在 5 分钟内看完这篇文章也不能在一分钟内为 CPython 和红姐加持的 Python 加上多行 lambda,但我有的是时间学。

大一寒假的时候我在学校里学C语言的补码时候学会了一种十进制换成二进制的方法,不知道学计算机的是不是也是这么算的,感觉比高中数学课教的那除2取余的方法快多了,而且容易掌握和不需要笔算。。。

首先我要吐槽一下,要知道计算机怎么算,为啥不看 libc source?不过一般都是取余的... 取余我不知道机器层面怎么实现的,据说是靠逻辑位移动?

首先作者举例
toHex(35) =
0x10 * 35 / 16 +
35 % 16 * 0x1
= 0x23 (这个是我靠着对 Nat 的理解强行猜的,当然我用别人教的方法也不差)

toHex(100)
= 16 * 6 + 4
= 0x64

toHex(1024)
= 16 * 64
= (需要进位64 = 16*4) 0x400

哦,我知道了,原来他是先算出 base=16 进位的数目,然后手动进位...

看出规律了吗?因为16进制的每一位可以对应4位的二进制数,... 我这么说可能十分不清楚,但也懒得去想更好的表达方法了,如果有人看不懂再说

嗯,这个本频道之前也提到过,至少我教过你们手动编码 base64,想来也不可能不告诉过你们 0x 是 0b 的简记法,因为 2^8 = 4*4 = 16, 或者说 log2(16) = 4

下面说的有点复杂

四位二进制数分别是8 4 2 1,比如说,16进制的3,就是2+1,就是0011,16进制的5,就是4+1,就是0101,意思就是说每一位16进制数都可以表示为8,4,2,1这四个数字的加和,若使用到,则该位为1不使用为0。我这么说可能十分不清楚,但也懒得去想更好的表达方法了,如果有人看不懂再说

我给个 table,就是说单纯四位二进制(之中一位为 1,其他都 0)

0b0001 = 2^0 = 1
0b0010 = 2^1 = 2
0b0100 = 2^2 = 4
0b1000 = 2^3 = 8

为啥要 (-1) 是因为我们算的是进位,看不懂算了(其实不是的,是我弄错 factorial 的定义了,后来改正了)(我也不清楚,爱因斯坦说过,如果你不能把道理给小孩子解释明白,那你自己也不懂,这是说我自己)。

比如说,16进制的3,就是2+1,就是0011,16进制的5,就是4+1,就是0101,意思就是说每一位16进制数都可以表示为8,4,2,1这四个数字的加和,若使用到,则该位为1不使用为0

0x3 = 0x2 + 1 = table[2] (0b0010) + table[1] (0b0001) (这是 16 到 2 快速换算法,类似乘法口诀,你尝试把数 n 与表中最近的整位相减,然后把余数这么做...)
0x5 = 0x4 + 1 = table[4] (0b0100) + table[1] (0b0001)

0bXXXX pat
0b0 <+8> <+4> <+2> <+1>
按这个 pattern 算,最大和为 15,就是 0xF

至于上面的 0x 0b 什么的,就是 C 风格的 16, 2 rhs literate 支持,我也不知是.... 前面第一位 0 是为了要有一个占位的

那么按照这个规律,你现在可以来尝试算一下十进制的307等于多少

就是 toBin(toHex(307)),我算算

307(10)
= 0x1 * 307 %16 +
let _10_0 0x10 * 307 / 16 +
然后我们发现 _10_0 大于 16,可以进位... 该死,我应该递归的,为啥要循环呢?(滑稽)

那么递归用 Haskell 很好写,我们来看看流程,反正我们是在编程:

+ 输入一个数 n,我们要一个 String,和当前进位的数值,它的字符串表示
+ 字符串表示 0x0 - 0xf,分别对应 0-15
+ 那么就有了一个递归程序,可是,算法是:

所谓自然数计数法,就是 0xFFF = (16^2 * 1) + (16 * 1) + 15
好吧,还不直觉,是 11 = 10 +1, 100 = 10^2*1 + 10^1*0 + 10^0*0
言而总之,就是把一个数化为数位相加的形式,这个过程中,如果我们用类似 C 的结构化方法,就是:

arg n
base = 16
var outs
ret n
for d = map (factorial base) (1..)
var r = n % d — rest
n = tailrec(n / (n-r)
)
outs « toHexDigit(n) « toHexDigit(r)
— 一个是进位的,就需要递归,一个是剩下本位的

那么我们来验证算法的正确性(一定程度上,你们都知道我在熬夜并且是算法垃圾)

n = 100

for, d = 16^1 = 16
r = 4
n = 6
outs = "0x64"
🤔 那就暂时认这个,虽然我知道它不对... 管他呢

307
= (算个位) 递归 (307-16^1) + 3 (16 余数,要进位的数)
= (16^1) 递归 (259-16^2) + 3*0x10 |(16^0) +3
= (16^2) |+3*0x10 |+3*0x1

🤔 ... 看来没写出来呢。我还是手算算了

307
先算 307 mod 16 = 3 (个位)
算进位 (307 - 307 mod 16) / 16 = 19
19 大于 16,再次进位到 0x100 "1",16^1 位为 19 - 16 "3"

综合,得到 0x100*1+0x10*3+0x1*3 = 133(16) = 307(10)
然后再算 toBinary(0x133)

考虑一下 4 位最大达到 8 + 4 + 2 + 1 = 15,完全不够,所以 drakeet 之前教的速算... 不得不说对这个没用
那么就继续往下推,下一个 "8 4 2 1" 是 reverse . take 10 $ (2^) <$> [0..]
128,64,32,16

那好喽,就这么算呗,我自己曾经也造过这表
...
0x133
= 128 + 5
= 1000 0000
| 0101
= 1000 0101

完成了!

最后,再检验一下,我们可以反过来算一遍,比如随便拿一个二进制数,0101 1111 1110 这个数换成十进制是多少呢?你肯定不会再拿笔来算各位成于2的n次方的加和吧

0101 1111 1110 = 0x500 + 0xF0 + 0xE = 0x5FE
然后再去做就可以了,『并行化』乘除法计算

那么就是这样,不过我觉得就是个口算优化...

最后 drakeet 写了个 Java 的输出 int32 binary digit,每 4 位一个空格的程序,其实也可以用 C 写一个(其实嘛位运算很入门的,还不如他上面教的算法有趣...),我写

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
if (argc != 2) return -1;
int32_t n = atoi(argv[1]);
fprintf(stderr, "Got %i\n", n);

char digit;

// output binary
for (short int processing_bit = 0; processing_bit < 32; processing_bit++) {
digit = 0b1 & (n >> processing_bit); // little endian reverse

if (processing_bit %4 == 0 && processing_bit != 0) printf(" ");
printf("%d", digit);
}

printf("\n");
}
#C
[DuangSUSE@duangsuse]~% ./digit 256
Got 256
0000 0000 1000 0000 0000 0000 0000 0000
[DuangSUSE@duangsuse]~% ./digit 1
Got 1
1000 0000 0000 0000 0000 0000 0000 0000