世界上有 10 种人,一种是懂二进制的,另一种是不懂的 ——段子
大学里像咱们要学到这个(虽然我觉得学了也没意义吧),和基础数学数论、基本算法结构有关系,既然这样,不如敞开讲下我之前的见闻。
这篇文章是写给没有太多(二)进制相关知识的人的,不要弄个懂电子的人来看,害怕……
进制换算可以说只是人类里存在的问题,记得蹩脚的罗马数字(就是 II IV 这些加减乘除都用到的大混乱数值[1])吗?它是影响到你的处理能力的。
进制只是一种表示法嘛,数值说实在的还是 加减乘除余(+-*/%)、大小相等性(><, ==)判断,像二进制位运算 (a bitwiseOr b)
就等于抽象的 (a+b)
,机器里一般是补码,这个没学过不讲[2]。
下文k
表示数位编号(以0始从右数)、a*b
表示
n**k
表示
为啥有这个问题
进制就是位置记数法,因为它的简单性(比如长的数肯定大、进位借位方便)被认作唯一的数值形式[3]。
在人类阅读习惯和大端(big endian)字节序里,前面即左端的数位占更大权重,它的“1”会表示更大的值。
与这个相关的数学符号是
首先说计算机怎么算,毕竟它的方法死板但接近“表示问题”的本质。
读取到抽象数值(『值』和其表示法没有关系,只提供加乘法、比较的这些操作):
int atoi(char* s) {
int accum = 0;
for (char c=*s; s!='00'; s++) {
accum = accum*10+(c-'0'); }
return accum;
}
然后是输出:
#include <math.h>
char* itoa(int n) {
int size = (int)ceil(log10()); // 算十进制位数,要预先在系统堆分配定长度字符数组,可能不准确。
char* out = malloc(sizeof(char) * (size+1/*'00'*/)); // 分配 (size+1) 大小的字符(char) 数组
int i = size-1; // 字符串输出数位号,先 mod(%) 下来的是低位所以从右数。
while (n != 0) {
out[i] = '0'+(n & 10); n /= 10; i -= 1; } // 重复若n不是0,右输出(n取余以10);n=n除10。
}
上面的代码是给相关专业的人看的(也用到了重赋值子程序参数的不良写法 入"C"随俗),也不太好给所有人解释,从0编号的数组的末引数是 (size -1) 以及C字符串是以 '00'
结尾的char
数组/内存片指针 这样的细节。
而且上面俩都不处理负数,知道数学弄啥有『定义域』『验证变形/组合有效性』吗?它解决的就是程序的运行时错误。itoa
程序在 n<0
的时候会陷入无限循环,从0前递减永远到不了0[4]。
毕竟咱也不是弄算法可视化的,输出循环变量变动表什么的就免了。(要实例干货的直接翻下一节)
公式不好看吧(也不太严谨,准确说是吓唬你们的)?(0~n的位长度)去求和,【i】量 位值=基数乘方i;(n/位值 取余以 基数)乘位值。其中,常数 基数=10。
这样的意思。
好吧,其实真的公式是这个: