不借助现成工具,亲身手动解决是加深对问题理解的不二法门。不过,有时候重复繁琐的步骤真是令人厌烦。这时既手动又自动的方法,是按手动的方法写个工具解决,而不借助现成的工具。
例如,十进制小数转二进制。(0.5)dec->(0.1)bin手动的方法在计算机导论、数字电路课里都有,这个方法的名字叫 乘2取整。课本里有,在此不赘述。
Excel 中没有函数可以输入十进制小数给出二进制。在这里,我们按手动解决的过程,用Excel求十进制小数的二进制。
1. 效果演示
其中第二行中的0.14是输入的十进制小数;
第三行是输出的二进制小数,每个单元格对应二进制小数的一位。
如果我们想换个十进制小数,例如 2.718,那么修改0.14为0.718,二进制小数的每一位会自动更新。
如果我们想要二进制小数点后更多位数,那么把最后一位的两列向右复制。
验算操作是 复制第三行(取整)中所有二进制小数位,在第五行(小数进制|验算)选择性粘贴为数值。
验算的过程在下图的最下面三行中。
验算结果在最底一行(转十进制)中,0.7179……,由于精度不足所以有误差。
通过第三方工具交叉检验,https://www.inchcalculator.com/decimal-to-binary-converter/,如下图所示与上述Excel工具的结果一致。
2. 公式
自行制作这个Excel的步骤很简单。
模仿课本里的手动方法,乘2、取整两步。
乘2 这一行,除第1个数即输入的十进制小数,
其余每个单元格的公式都类似“=IF(D2<1,D2,D2-1)*2”。
其中,D2是当前单元格左侧的那个单元格。
这个公式的含义是 把左侧的单元格乘2,即 乘2操作。稍微有点细节需要考虑,乘2取整法要求每次运算都舍去整数部分。在这里,考虑最大的小数为0.9,乘以2以后为1.8,因此整数部分不会大于1。进一步,整数部分只有两种可能,1或者0。如果整数部分为1,那么减1以后再乘以2;如果整数部分为0,那么把小数部分乘以2。
以上是 乘2 这一步。
取整这一步,每个单元格的公式都类似“=IF(E2<1,0,1)”。
其中,E2是当前单元格同一列上一行的那个单元格,即乘2以后的结果。
这个公式的含义是 如果乘2的结果小于1,那么整数部分为0;否则整数部分为1。
复制这一列的两个公式,粘贴到右边的每一列。粘贴列数的多少,取决于你希望有转换时精度达到何种程度。
验算有两个公式,即 按权相加 的两步。
其一是 求每一个二进制对应的十进制权重,所谓“按权”。
其二是 对所有位求和,所谓“相加”。
这样,就可以用Excel完成十进制纯小数转换为二进制了。任意小数的整数部分,可以单独手动处理,用计算器、Excel都容易完成。
3. 开发过程及考虑
初学程序设计,对编程思路不熟悉,或者对excel不熟悉,看了上面的公式可能会有挫败感。“你怎么一下子就把这些写出来了,我做不到啊。”
有人确实能做到,你做不到也不需要焦虑,我也做不到。我并非一步写出来的,过程如下。看了步骤你就会发现,我很笨,连我这么笨也能写出来,你当然也没有问题。
第1步
这里没有任何公式,只是把架子搭起来。你可能觉得,这有啥啊。反正我每次搭完架子,写完main函数,都要反复看一会儿,自矜半晌。这个架子提示我以后哪个变量要放在什么地方。右边的那些,不是截掉了,而是最初根本就没有,反正要用公式复制粘贴算出来的,现在写上,只是影响我的注意力,降低我的自信心而已。
第2步 乘2
啥东西乘2呢?所以,我要先写个十进制纯小数,并且先验地知道它的结果。位数还不能太少,不然检测不出bug。
就0.718吧,找个工具算一下。
在运行我写的每个程序以前,我对它的结果一定是有预期的。运行的目的不是探索“会是什么结果呢”,而是要么符合我期待的结果,我的程序可能没毛病,要么与我期待的结果不同,那么程序肯定哪里错了。
我输入0.718,乘2(再取整的)结果一定是1011才对。
下图中,0.718是我输入的,待求的十进制小数。公式,就是乘2,没有最后结果那么复杂。
我扫了一眼,乘2乘得不错。你可能看出来了,我没有减1,但是当时我并不知道——而这,也没什么影响,我们不必一蹴而就。遇到问题,解决就是了,等遇到问题再说,眼下我还没看出来。
第3步 取整
如下图所示,我给了公式 对同一列上一行 取整。取整的这个函数,是我 bing 搜索到的。关键词当时用的什么不确切地记得了,大致是“excel 取整”。此时如果你不知道 floor, ceiling, round 这些区别,可能这里会纠结一会儿。无妨,即使不知道这些,如果发现问题了,换个公式就是,后面会换的。
这时,我会发现个问题,这也是程序为什么需要 调试 的原因。
这工作马上就完事了,乘2么、取整么,一共就两步,所以就完了。当任务“完成”以后,或者说每次认为完成以后,需要检验是否符合目的。我的目的是把——我跳到标题复制来的——十进制小数转二进制。目标是二进制。但是在结果里出现了2及2以外的数,按说只应该有0和1才对。
第4步 调试-修改
为什么结果里有2,那是因为同一列上一行的那个数字的整数部分就是2。
为什么结果里有5,那是因为同一列上一行的那个数字的整数部分就是5。
所以,取整 没有问题。那么问题出在 乘2里。
我可能需要查一下课本。你可能更厉害,连课本也不用查,就意识到,“乘2”不对望文生义,根据课本中的叙述,乘2这个操作的输入不是上一次的结果,而是上一次的结果取出小数部分。我漏了取出小数部分。
怎么取出小数部分呢?这是比刚才所有讨论更细节,因此也更微小的问题。你可以用完全和我不同的手段,比如求余(求模),转成字符串然后找小数点再分割……无所谓好坏,顺手就行。别忘了,这是个微小的问题。是的,我作为教师可能会PUA你,有更好的方案。然而,为什么要追求更好,什么指标才是更好,就这么十几二十几位数字有性能问题吗?可维护性好不好有那么重要吗,这个技术手段用于一个可抛弃的学习用的工具,而且已经把这个技术手段隔离在这个单元格中了,不会污染其他的部分。最关键的是,这个问题它微小,对全局的技术路线没什么影响。
我把公式改为 =IF(C2>1,C2-1,C2)*2
我还查了一下excel中的if这个函数的参数。第一个参数是逻辑判断的条件,如果为真那么返回第2个参数,如果为假那么返回第3个参数。
复制这个公式,粘贴到 乘2 这一行的其余单元格。好像又很对的样子,根据下一行 取整 的结果。
看起来对了。
你可能不放心,取整 那行公式对不对啊。不知道,而且和我的最终版本不一样。如果增加信心呢,多测几组数据。如果这些数据有代表性,那就更好了。如果有代表性,是个巨大的问题,此处无法展开。也可以“尽力而为”地测几组数据,出了问题——再说。
我测了 0.14,0.718,与交叉检验的结果都一致。
又测了0.01234,结果太糟糕了,全0。我不知道转换的结果是什么,不过肯定不是全0。
为什么呢?噢,因为精度不够。
复制最后一侧,向右粘贴。
很像对的样子,不是全0了。
交叉检验,果然很对。
你可能发现了,第一行后面的数字是错的,我复制并粘贴了“4”。后来我改了,在此不再截图。
4. 补遗
验算,不是标题“十进制小数转二进制”的一部分,因此它的公式怎么一步步改出来的,略去。
我还顺手做了个十进制整数转二进制。
二进制从右往左读。
公式1 除2
公式2 除余
公式3 费了不少步骤,只是为了练习、学习或者手痒,Excel内置了整数十进制转换为二进制的函数。
此文也发布在以下站点。
----
知乎 https://www.zhihu.com/people/yang-gui-fu-52
独立博客 https://younggift.net/
微信公众号 杨贵福
----
以下是我曾经发布博客的站点,有些旧文。
----
豆瓣 - 因为审核"我的日记",不再更新。
https://www.douban.com/people/younggift/
CSDN – 因为要求我登记手机号码的原因是“为了您的安全”,不再更新。
https://blog.csdn.net/younggift?type=blog
blogsopt – 因为从我的机器不可达,无法更新