小名开开

在春天的光影里喘息

Excel 很多时候可以当作一个简易的数学计算程序,代替 Mathematica 或者 Matlab 之类的专业软件进行一些不算太复杂的数值运算。但 Excel 的数据处理存在很多弱项,在遇到时需要相应作一些处理。

问题一:有效位数大约只有 15-16 位,更多的位数只会用 0 填充了。

1

精确计算的 2n 的尾数不会是 0,始终是 2→4→8→6→2…… 的循环,但从截图上可以看到,Excel 在计算 250 时,就遇到了有效位数问题,使得末尾出现了数字0。

关于问题一的应对:

从例子中可以看到,Excel 提供了 15 位的精度,这意味在在『千万亿』这个级别上 Excel 依然可以进行精确的计算。相当于以小数点后 4 位精度,即 0.0001 元 = 0.01 分 的精度下,处理九千亿人民币以下的财务数据。处理全国 GDP 的数据也可以精确到分,以米为精度可以让光跑一个月,以毫秒为精度覆盖三万多年。

但是如果你真觉得不够,就需要自己用公式实现进位,使用多个单元格作为『数字段』,来确保每个单元格内的数字长度不超过 15 位。

以 2n 为例,其计算由两部分组成:

最右一列公式为:

1
2
3
4
5
Z1=2
Z2=TEXT(RIGHT(Z1*2,12),"000000000000")
Z3=TEXT(RIGHT(Z2*2,12),"000000000000")
Z4=TEXT(RIGHT(Z3*2,12),"000000000000")
……

其中,Right 函数保证每个单元格只取结果的最右 12 位,让精度始终符合 15 位上限的要求。而 Text() 函数则保证当截取 12 位数字时,不会将原来在中间位置的 0 因为截取而成为首位 0 消失掉。例如,263 = 461,1686,0092,1369,3952,当截取 12 位时,会获得0092,1369,3952,如果不通过 Text() 函数保存首位的 0,则最后合并回去时就会产生错误。

左边每一列的公式均为:

1
2
3
4
X2=TEXT(RIGHT(Y1*2+IFERROR(VALUE(LEFT(Y1*2,LEN(Y1*2)-12)),0),12),"000000000000"); Y2=TEXT(RIGHT(Y1*2+IFERROR(VALUE(LEFT(Z1*2,LEN(Z1*2)-12)),0),12),"000000000000")
X3=TEXT(RIGHT(Y1*2+IFERROR(VALUE(LEFT(Y2*2,LEN(Y2*2)-12)),0),12),"000000000000"); Y3=TEXT(RIGHT(Y1*2+IFERROR(VALUE(LEFT(Z2*2,LEN(Z2*2)-12)),0),12),"000000000000")
X4=TEXT(RIGHT(Y1*2+IFERROR(VALUE(LEFT(Y3*2,LEN(Y3*2)-12)),0),12),"000000000000"); Y4=TEXT(RIGHT(Y1*2+IFERROR(VALUE(LEFT(Z3*2,LEN(Z3*2)-12)),0),12),"000000000000")
……; ……

这个公式同时适用于左边任意多列,使得只要电脑性能过关,尽可用尽 Excel 的所有列(一共 16384 列)。

公式略复杂,以 Y2 为例:

1
Y2=TEXT(RIGHT(Y1*2+IFERROR(VALUE(LEFT(Z1*2,LEN(Z1*2)-12)),0),12),"000000000000")

最外层 Text() 依然是为了保留首位 0。Value(Left()) 用于提取右边列的进位数字,即当前列的右侧列如果出现超过 12 位的数字时,则截取头部进到本列。Iferror() 用于检测是否进位。将进位数字和本列上一行数据乘二的结果相加后,再检测是否本列也多于 12 位,如果多则截取。公式引用关系如下:

I9N46D5M6%U}E@8IXWXS8CU

使用类似思想,可以精确进行一次数值变化不超过 1014 的大部分大数计算。需要注意的是,假如一次数值变化较大,则每单元格所能保留的位数就相应变小,不一定是 12 位了。

应对问题一的要点有二, 一是自行实行截取与进位,二是利用 Text() 公式特性,保留截断后的首位 0 不丢失。我通常把这种处理办法称为『大数多列化处理』。

问题二:数值上限大约在 21024-1,由于有效位数限制,实际上限更小一点,大约在 21023+21022+……+2971 ≈ 1.7977e308 左右。

2

这与问题一不同点在于,这个问题不关注精确展开,而更关注公式计算过程中的上限值。当然,使用问题一中的办法也能解决本问题中的部分情况,但对于更大的数字,例如用尽 Excel 所有列(16384列)也写不下的数字,大约 1016384*14 = 10229376,问题一中精确展开的解法就无能为力了。况且在实际展开中,在装满 Excel 前就早早会遇到内存和 CPU 瓶颈了。问题二的解法注重于在有限的计算资源下计算尽可能大的数字。

我们以计算 361 的阶乘为例,如果使用 Excel 公式直接输入 =Fact(361) 则只会得到一个 #NUM! 的结果。意即该计算的值或者计算过程中已经出现了超过 Excel 单元格所能容纳的最大值。

关于问题二的应对:

我们在 Excel 中准备三列数字,A 列为从 1-361 的展开。C1 公式为 =FLOOR.MATH(LOG10(A1)),B1 公式为 =A1/10^C1。

从 C2 起公式为:

1
2
3
4
C2=FLOOR.MATH(LOG10(B1*A2))
C3=FLOOR.MATH(LOG10(B2*A3))
C4=FLOOR.MATH(LOG10(B3*A4))
……

从 B2 起公式为:

1
2
3
B2=B1*A2/10^C2
B3=B2*A3/10^C3
B4=B3*A4/10^C4

于是形成如下形式:

![1~P8Q1T0%@[@S4J1CS4Y`U9](../attach/2016/03/1P8Q1T0@@S4J1CS4YU9.png)

即 B C 两列形成了类似科学计数法的 b × 10 c 的数列。但不同之处在于,C 列的所有值全部相加,才是整个计算过程的最终解,如图:

EXWL~KE6X(5_2I4BLEN}%E5

即:361! = B361 × 10 SUM(C1:C361) = 1.43792325888489 × 10768,和上一篇博客对照一下,结果还是很精确的。

仔细观察 B、C 两列数值,其实原理就是每当一个新的 A 乘进来,都对结果作一次科学计数法处理,形成 b × 10 c 结构,确保每一次都有 1<b<10,然后把乘方 c 扔在一边最后再相加。

这一解法的关键在于在计算的每一步都即时处理,避免单元格数字过大而『爆掉』。通过这种方法,Excel 的可计算数域范围从大约 10308 变大到了大约 101,0000,0000,0000,0000,更大的数字则会产生 10 ~1000 倍甚至更大的误差。但如果对 C 列的数字再作问题一解法中的多列化处理,则可计算数上限大约会变成 1010229348 ,这里被迫用了幂的幂。这个数字相当大,并且实际不可能用到。早在这个极限之前,你的电脑内存估计就会挂掉。

当然,因为有 VBA,Excel 理论上也可以做复杂大数字计算,但考虑到学习成本和应用场景,不如学习 Mathematica 来得方便了。一般使用 Excel 做计算,都仅限于操作单元格和自带公式可以解决的问题。

最近 AlphaGo 与李世石的人机围棋大赛很火,也蹦出一大波跳梁小丑。你会发现什么热点事件都少不了这种人,总是挡在路上污人视线,比如那个输入法王。我记得上次 SoloLens 它也跳出来大谈 Matrix 来着。

牢骚完毕,这次深夜短篇不是写围棋也不是写计算机的,只说数数,更严格的说,只是数『0』。比如:

围棋棋盘共有 19×19 个点,每个点有『无子』、『黑子』、『白子』三种可能性。不考虑无气提子等特殊情况,则一共有 3^361 种盘面。如果考虑到下子进程,则有 361! 种棋谱。

因为有围棋规则在,实际数字会小一些,但这不是本文重点。这两个数字分别是一个 173 位数和一个 769 位数:

1
2
3
3^361=17408965065903192790718823807056436794660272495026354119482811870680105167618464984116279288988714938612096988816320780613754987181355093129514803369660572893075468180597603

361!=1437923258884890654832362511499863354754907538644755876127282765299227795534389618856841908003141196071413794434890585968383968233304321607713808837056557879669192486182709780035899021100579450107333050792627771722750412268086775281368850575265418120435021506234663026434426736326270927646433025577722695595343233942204301825548143785112222186834487969871267194205609533306413935710635197200721473378733826980308535104317420365367377988721756551345004129106165050615449626558110282424142840662705458556231015637528928999248573883166476871652120015362189137337137682618614562954409007743375894907714439917299937133680728459000034496420337066440853337001284286412654394495050773954560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

呼应本文标题的问题来了——这两个数字末尾各有多少个『0』?

你当然可以靠眼力劲儿去数,前者容易看出末尾没有 0,后者大概费些功夫能数出有 88 个 0。当然你也可以使用查找替换,数起来方便些。

但是如果没有事先把总数算出来,又如何数出一个数的末尾有多少个 0 呢?毕竟连乘 300 多次算个 700 多位的数字恐怕是更累的一件事情。能少算就少算点吧。

办法是有的,数质因素 5 就可以了。

要注意到,无论多少个数连乘,只有 2×5 才会在末尾添加一个 0。有人说 8×5 也会出 0,4×25 会出两个 0。但 8×5=40=22x2x5,有两个 2 其实浪费掉了。而 4×25 = (2×5)2,本质上正好是两对 2×5 相乘,完全符合之前的设定。又因为在阶乘中,2 作为质因数的出现次数远远超过质因数 5 出的次数。每个偶数都能至少贡献一个质因素 2,而每个 5 个数字才能贡献一或若干个质因数 5。因此可得结论:

只要数清连乘中一共有多少个质因数 5,就知道最终数字末尾有多少个 0 了。

对于 3^361,显然一个质因数 5 都没有。所以末尾没有 0。

对于 361!,

  • 每隔 5 个数字,可以提供一个 5。即 5, 10, 15, 20, 25, 30, ……, 360。一共 361 / 5 向下取整,有 72 个。
  • 每隔 25 个数字,可以一次提供两个 5。即 25, 50, 75, ……。一共 361 / 25 向下取整,有 14 个。由于上一条已经重复计算一次,因此这里的 14 不必再翻倍了。
  • 每隔 125 个数字,可以一次提供三个 5。即 125, 250。一共 361 / 125 向下取整,有 2 个。由于上一条已经重复计算一次,因此这里的 2 不必再翻倍了。

再上去是 625,直接超了。于是数 5 活动就此停止。

一共有 72+14+2=88,而 2 的数量肯定是足够的,于是会产生 88 组 2×5,即末尾有 88 个『0』。

这个方法可以广泛用于各类无聊的数 0 活动中,例如:

任取一个足够大的数字 N,比如 10100 即 1 googol,把小于 N 的所有素数乘起来,那么多素数的乘积的末尾有几个 0?

——答案是只有一个 0,算对了么?

那么第二个问题来了,为什么数 5 知 0?

答案是,这个和 10 进制有关。

仔细思考,『进制』的本义就是每满多少就 归 0 进位。换句话说,如果 要让末尾为 0,就必须不多不少,最末尾那些余量恰恰等于当前进制。这个 『余量』不是严谨的用词,意会即可。在 10 进制里,你总要正好凑出 10 个或者 10 的倍数个,才能让末尾是 0。在 8 进制里就要凑 8 的倍数个让末尾是 0。16 进制凑 16,N 进制凑 N。

所以归根结底,要让若干个数连乘得到末尾零,就是看能凑出几份当前进制。10 进制就是要凑 2×5,8 进制要凑 2x2x2,每三份质因数 2 会多一位尾 0,只看 2,别的都没用。

既然 10 进制下,10 的唯一质因数分解就是 2×5,而 2 又远多于 5,所以数 5 知 0 就变成了最简单的办法。

理解了这些,下面这些问题也不难回答了:

3361在 3 进制下,末尾有几个 0?

答案是 361 个 0。这个问题等效于 10 进制下 10361末尾有几个 0,等效于 N 进制下 N361末尾有几个 0。——都是361个。

21024在 16 进制下,末尾有几个 0?

答案是 256 个。因为 16 = 24,1024 / 4 = 256。

最后一个问题:

31024在 2 进制下,末尾有几个 0?

HTML 5 提供的 <audio> 给了前端相当多的方便,不再需要 js 库和 swf 作为播放器。但是新带来的坑也是坑得我要死要活的。

这是 W3School 提供的一张简表:

Browser MP3 Wav Ogg
Internet Explorer YES NO NO
Chrome YES YES YES
Firefox YES YES YES
Safari YES YES NO
Opera YES YES YES

信了你就掉坑了。

HTML5 的 <audio> 有着比看起来的大得多的坑。主要在于各浏览器的实现上有区别,自带的音频解码器各有不同,导致实际支持的格式各有不一。

并且,在宣称支持的格式里,各浏览器也只支持其中一部分编码格式。例如:

Firefox、Chrome 可以正常播放 Microsoft PCM, 16 bit, mono 8000 Hz 的wav,但是无法播放 GSM 6.10, mono 8000 Hz 的wav

以及来自于 这篇文章 的:

Playing MP3 files in Firefox is actually OS/hardware dependent. That’s right, instead of using a built in, true native support, we have to rely on outside variables that we have no control over. Kind of defeats the purpose of that whole no extensions, native support thing that HTML5 is good for. Yes, this is to avoid patent issues (and so Mozilla doesn’t have to pay licensing fees). If you are serving to a lucky person below, here’s the real MP3 support for Firefox:

  • Windows 7+ (Firefox 21.0)
  • Windows Vista (Firefox 22.0)
  • Android (Firefox 20.0)
  • Firefox OS (Firefox 15.0)
  • OS X 10.7 (Firefox 22.0)

大意是 Firefox 的 MP3 播放支持其实是依赖于系统和硬件的,这样可以免去专利费。相应的,支持列表就变得有点复杂了。

这里有几个测试页, 可以大致用来测试主流浏览器的音频文件支持情况,但是也不完全。就如上文所述,Chrome 对 wav 文件只能说部分支持。

测试页一:http://hpr.dogphilosophy.net/test/

测试页二:https://html5test.com/

所以在实际测试中,某浏览器播放不了指定音频有两种可能性:

  • 音频格式不支持
  • 音频编码格式不支持

对于相关的编码格式,大致查了一下,列表如下:

OGG

同样后缀名为 .ogg 的音频文件,可能有以下几种编码格式: Vorbis, speex, OggPCM, FLAC,其中,Vorbis 是被建议的。

WAV

.wav 文件通常被理解为原始采样,未经压缩。但其实并不一定如此。最广泛标准的 .wav 文件是指微软 PCM 编码的音频文件(其实也已经编码过了,毕竟从模拟信号转数字信号无论如何都会有一个采样过程。)PCM 细分又可分为定长(16bit、32bit 等)和浮点两类。另外.wav 还可能是 GSM 编码格式,这种格式广泛使用于通讯网络,但在互联网上并不常用,最有可能的来源是电话录音导入电脑。

MP3

MP3 规范并没有详细规定如何编码,但却有细致的解码定义。也就是说『符合这一类规范的才叫 MP3』。因此,MP3 的格式反而才是最一致的,除了采样率、变长/定长和声道数量外,不存在其它变化。

Opus

Opus 是设计为同时包含音频和视频的编码格式。* 可以取代复杂的编码后封装方案。但实际上普及率很低,支持也不好。

AAC

AAC (Advanced Audio Coding)主要是得到了苹果的支持。但除此以外,在互联网的使用并不广泛。

Mozilla 提供了另一张更为详细的表格:(注意这个表还是只能作为参考)

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 3.0 3.5 (1.9.1) 9.0 10.50 3.1
<audio>: PCM in WAVE (Yes) 3.5 (1.9.1) Not supported 10.50 3.1
<audio>: Vorbis in WebM (Yes) 4.0 (2.0) Not supported 10.60 3.1
<audio>: Streaming Vorbis in WebM via MSE ? 36.0 (36.0) ? ? ?
<audio>: Vorbis in Ogg (Yes) 3.5 (1.9.1) Not supported 10.50 Not supported
<audio>: MP3 (Yes) (Yes) 9.0 (Yes) 3.1
<audio>: MP3 in MP4 ? ? ? ? (Yes)
<audio>: AAC in MP4 (Yes) (Yes) 9.0 (Yes) 3.1
<audio>: Opus in Ogg 27.0 15.0 (15.0) ? ? ?
<video>: VP8 and Vorbis in WebM 6.0 4.0 (2.0) 9.0 10.60 3.1
<video>: VP9 and Opus in WebM 29.0 28.0 (28.0) ? (Yes) ?
<video>: Streaming VP9 and Opus/VP8 and Opus in WebM via MSE ? 36.0 (36.0) ? ? ?
<video>: Theora and Vorbis in Ogg (Yes) 3.5 (1.9.1) Not supported 10.50 Not supported
<video>: H.264 and MP3 in MP4 (Yes) (Yes) 9.0 (Yes) (Yes)
<video>: H.264 and AAC in MP4 (Yes) (Yes) 9.0 (Yes) 3.1
any other format Not supported Not supported Not supported Not supported 3.1

所以解决方案大概就是先通过测试确定一两种被绝大部分浏览器支持的音频编码格式,然后服务器后端将音频文件转码为这一到两种适用的音频格式再传递给前端。

看起来最通用的是 MP3?简单地说,是的。但要注意的是不是任意一种 mp3 编码格式都支持,最优化编码的 VBR 支持性就存疑。同时,由于 Firefox 的 MP3 支持是基于系统的,所以假如 Ubuntu 没有安装 ubuntu-restricted-extra 包也可能出现支持性问题。

* 附:

更复杂的是 <video> 标签,由于视频通常是包含声音和图像两部分的,因此实际上视频文件数据是由已经编码的视频数据和已经编码的音频数据,再次进行数据交错编制而成的。因此除 编码格式 外,又衍伸出 封装格式 的概念。深受大家喜爱的 .avi 格式,即 Audio Video Interleave 的简写,就是一种封装格式。当你使用 avi 封装器折开文件后,就会见到一个无声的视频文件和一个无图像的音频文件。至于各自的编码格式又五花八门了。因此对于 <video> 标签的支持更加混乱,几乎必然需要通过服务器转码才能确保在尽可能多的浏览器上前端一致,这也是各视频网站为什么会有大量集群转码处理用户上传的视频的原因。

Update: Ubuntu 16.04 系的解决了这个问题。此文终结。


无标题

这个 Bug 出现在几乎所有版本的 VMWare Workstation、VMWare Fusion 而且按原理来说似乎也会出现在 VirtualBox 上(未验证)。用户选择右键点击喇叭图标手动连接,则可以使用一段时间,Rhythmbox 之类的也可以正常播放声音,但只要打开声音设置或其它类似操作就又会断开。

遇到这种情况,可以先尝试在宿主机接上麦克风/耳麦,随便弄个录音设置,或者把普通耳机插头插进录音孔也行。对的,尽管实际上录不了音,但只要让录音孔插着东西就行。无标题

然后重启虚拟机,如果一切正常该提示不再出现,就继续往下看真·解决办法,如果依然不行,很抱歉你的问题不是这篇文章所能解决的。

这个问题的真正原因是:Ubuntu 默认会检测音频硬件设备,包括音频输入和输出两种设置,但 VMWare 不能正常反馈宿主机声卡的状态。感觉更多的是 Ubuntu 的锅,它没有检测设备存在就直接调用录音设备。

解决办法:

1
sudo apt-get install pavucontrol

安装 pavucontrol 软件包,然后在 Term 中输入 pavucontrol 启动旧版的音量控制:

Ubuntu 64-2016-02-27-20-44-14

在音量控制界面,选择『配置』选项卡,选择『模拟立体声输出』,不要选任何带“输入”的项。然后注销用户再重新进入桌面。

Ubuntu 64-2016-02-27-20-45-50

以上,VMware Ubuntu 就可以正常出声了。

无标题

关于数组公式解释见这里:<Excel 数组公式的概念解释>

补充一个实际应用里出现的公式

1
{=INDEX($A$4:$A$27,MATCH(1,IF(ISERROR(FIND(C4,$A$4:$A$27)),0,1),0))}

作用是在 A组数据的各项文字中寻找到第一条包含 B 组词汇的数据,如图:

matchindex

原理是这样的,将 find()函数数组化,令其在 A4:A27 中逐个寻找 C4 中的『愿望』两字。当找到匹配时,Find() 函数会返回一个具体数值,即『愿望』两字在被查找的字串中在第几个字符出现;当找不到匹配时,则Find() 函数会返回 #Value!。在数组化后,返回的数组大致为

3DMark 是个显卡性能评测软件,通过运行一些实际的 3D 场景,给出电脑的 3D 性能评分。类似于国内的鲁大师评分之类的,只是 3DMark 更专注于 3D 性能评分而已。由于 3D 性能绝大部分实用场景都是玩游戏,所以 3DMark 自己的口号就是 『The Gamer’s Benchmark(是玩家就跑个分)』。

作为电脑的性能测试测试软件,自然是有不少榨压极限的测试项目,其中最耗资源的一项叫『Fire Strike』,寓意电脑满负荷运行时如同火烧一样。

就此为止这还是个正常的测试工具软件,然后软件公司就开了个脑洞。它添加了个全球排名榜(和打败了99%的电脑一样),还添加了 Steam 游戏成就……(⊙ˍ⊙)观赏一下:3DMark Game Archievements

于是一帮成就党和吐槽党就沸腾了:

Hevcy:
This game is the most pay-to-win game I have ever played. To have any hope of getting near the top of leaderboards you will have to spend at least 4-5k of your hard earned cash, and, to add to all of this, there is no gameplay to be found, just a series of cutscenes with no relevance to eachother at all. This is a grim sign of where the industry is headed.

– 这是我玩过的最氪金的游戏。你至少要花两三万辛苦搬砖赚的钱才有那么一丁点上榜的希望,关键是你攒起来了也没啥可玩的,就看那些没啥剧情的场景演示。这游戏行业怕是要走歪了。

MaxterChief:
I tried running the Fire Strike test. It just laughed at me, called me a loser and would have stolen my girlfriend if I had one.

– 我试着跑了下火焰冲击测试,然后就被它嘲笑了。它喊我卢瑟,还想抢走我女友,如果我有女友的话。

Modified420:
most expensive program ever.
1. Buy it.
2. Run it.
3. Go buy CPU/GPU.
4. Run it again.
5. Repeat from step 2.

史上最贵的程序
– 1. 买买买。
– 2. 运行软件。
– 3. 升级电脑。
– 4. 再次运行。
– 5. 从第2步开始重复。

Modified420
Just when you think you have a pretty good rig. This program will smack that thought right out your head, Stomp on that dream, and crush any hopes of possibly obtaining that Master PC status again until tax time. 10/10

– 你以为你搞了台牛机。这软件会狠狠拍醒你,告诉你别做梦了,也别觉得自己的机器能打败多少人了,还是搬砖去吧。

Señor Freezer
Cool software if you want your heart, hopes and dreams broken

– 你想让你心灵受伤希望幻灭梦想破碎的话这软件很不错。

Super Saiyan Papyrus
Pros:
Amazing Visuals
Intuitive menus
Global ranking system (by different classes)
Really fun to compete and see who is the best between all of your friends
Cross platform support for Windows Phone, Anroid, and iOS

Cons:
Pay to win

– 优点:
– 惊艳的视觉效果
– 直观的菜单
– 全球分类排名
– 基友之间撕逼谁最牛确实很爽
– 跨平台支持,包括 Windows Phone、安卓和 iOS

– 缺点:
– 氪金

Arctiix
Overclocked till my computer hit temps of 100 degrees Celsius to get achievements… No regrets.

– 超频到电脑 100℃ 拿成就……我不后悔(>﹏<)

moist
I got the CPU bottleneck and GPU bottleneck achievements at the same time

– 我同时拿了『处理器不够用』成就和『显卡不够用』成就。

Systemworks
Bought Alienware x51 gaming PC.
Ran standard Fire Strike test.

I bought a potato.

– 买了外星人 X51 游戏电脑。
– 运行标准火焰冲击测试。
– 我买的个山芋啊!(Hot potato 比喻棘手的问题、烫手山芋、使人厌恶的事。难题。)

♠ DgO ♠
The Fire Strike Ultra is so real that my PC got on fire.

– 超级火焰冲击很真实,我电脑着火了。

HEMI™
Lets face it we need this app to test our hardware and just make ourselves feel better about spending vast sums of cash on more hardware we really didn’t need just wanted 😉

– 其实吧,我们是需要这个 app 的。花了大价钱买了口水但实际根本用不上的硬件时,用它测两下,心里就不那么内疚了。

kinsey430
成就:0(以及以后若干年也会是0)
卡片:无
为什么买:要问2天前的我,顺便帮我劝劝他。

༼ つ ͡° ͜ʖ ͡° ༽つ
I own two Gtx 780’s and got the cpu bottleneck achievement.

– 我整了两块 GTX780 显卡然后拿了个『处理器不够用』成就。

Aoi
没成功运行过一次,歧视我没四路泰坦吗

[fwdcp] tsc
This is the most disgustingly pay-to-win game that I’ve ever played, and it’s not even interactive, more like a movie. I’m very disappointed.

– 最烂的氪金游戏,没啥互动,像个电影,我很失望。

Xenom73
Couldn’t handle firestorm at even 30fps. My epeen is deflated. Computer not worth any achievement score. Think i’ll cry myself to sleep.

– 火焰风暴跑不到 30 桢,我痿了。这电脑连个成就都挣不到,哭着睡了。

Drifter
Spent $1250 on a high-end computer.
Spent $5 to know that I made a terrible decision.

– 花 8000 买了台牛逼电脑。
– 花 30 发现我错了。

喵啦啦
卡吧标配游戏

Greenpool
I want to achieve the ultimate pleasure in life by unlocking all achievements. This is now my sole purpose to overclocking.

– 追求成就全解锁时的终极快感是我超频的唯一原因。

矢泽妮可
终于知道了我的电脑是战5渣..

观光链接:

header
http://store.steampowered.com/app/223850/

Excel 公式,本质就是输入原始数据,处理后再输出结果数据,放在公式的单元格里。

有些公式,输入是一个数据,输出也是一个数据,例如取整 int()、10 底对数 log()。若 A1=5.5,=Int(A1) 显示为 5。

有些公式,输入是一组数据,输出一个数据,例如 Sum。这一组数据整个是一个参数。若 A1:A5={1,2,3,4,5},输入公式 =Sum(A1:A5),显示为 15。A1:A5 数组是 Sum() 的一个参数。

有些公式,输入是一个数据和一组数据,输出一个数据,例如 Match(A2,A1:A5)。两个参数,A2 是待查数据,A1:A5 是被搜索的数组。

而数组公式,则是输入一组数据,输出一组数据

以 Match() 为例,Match 公式的形式为 =Match(lookup_value, lookup_array, [match_type]),其中 第三参数 match_type (查询模式)在本文讨论中忽略。则本文讨论的简化为 =Match(lookup_value 待查询数值, lookup_array 被搜索数组)

可以看到,一个 Match 公式一次只能在 lookup_array 里查找一个数值。而把 Match 公式改写为数组公式,并用 Ctrl+Shift+Enter 确认以后,实际公式则变成了 {=Match( lookup_value_array, lookup_array, [match_type] )}。

在公式里,本来应该是单一数值的地方,被替换成了一个数组,待查询数值 变成了 待查询数组。则 Excel 会自动响应 Ctrl+Shift+Enter 命令,把该公式拆分成多次分别执行,每次取待查询数组里的一项,单独给出一个结果,然后循环到该数组里的每个元素都被查询一遍。

例如,选择 C1:C5 单元格并在公式栏中输入 =Match( B1:B5, A1:A10, 0 ) ,按 Ctrl+Shift+Enter 回车。Excel 会自动内部展开五次 =Match() 查询,每次查询在第一个参数位分别填入 B1 – B5。即在 A1:A10 中分别查找 B1 – B5 的值,查 5 遍,并把 5 个结果分别放在对应的 C1:C5 单元格里。

array_match

所以:

1. 因为往往有多个输出结果,使用数组公式需要先选择好输出位置,再在公式栏写公式,写完用 Ctrl+Shift+Enter 确认。注意,这多个单元格包含的是『一个公式』。

2. 数组公式需要你在写公式时,把『一个数据』的参数改写为『一组数据』。(例子中 Match() 函数本来的 lookup_value 即『需要查找的值』改成了『需要查找的数组』。)Excel 会自动循环这个改写数组里的每一个数据,然后把公式计算结果填到对应的单元格里。

3. 数组公式修改起来较为费劲,经常会出现『不能更改数组的某一部分』,正确的方法是先按 Ctrl+/ 全选该数组公式的整体占用位置,然后再在公式栏进行修改。

4. 某些公式,例如 Sum()、Len() 使用数组公式和直接使用该公式往往没有区别。所以如果你见到某个教程在以 Sum 举例讲数组函数时就不用往下看了。百度搜出来有不少是这样的。

5. 一般来说,常用的数组计算 Excel 都已经提供了特定的函数,比如 Logest()、Frequency 等。如果返回的值有两个以上的,也通常都拆成了多个公式,比如线性回归的 Slope()、Linest()、Steyx() 等。当需要多个计算结果时,也无需使用数组公式,使用 Excel 的公式复制粘贴就可以完成绝大部分工作。上文的例子即是如此,选择 C1:C5 然后输入 Match() 数组公式,和先在 C1 输入普通的 Match 公式 =Match( B1, $A$1:$A:$10,0 ),然后把公式复制到 C2:C5 上,效果是一样的,后续处理起来还方便一些。

那么数组公式有什么用呢?

大部分情况其实没什么用,确实没什么用,所以很多人用了好久也没用过数组公式。哲学点地说,等到你需要用数组公式时,数组公式就有用了。

数组公式的最大特点是『输出的是一个数组』,所以它需要用多个单元格才能放下,同时,它可以作为数组参数供其它函数使用。所以数组函数最大的使用场景是通过复杂嵌套函数,实现更大程度的 Excel 自动化。

例如,去除重复单元格,可以使用 Alt+A+M 的『删除重复项』实现,但这样意味着每次数据更新,都需要重新进行人工操作,当处理步骤较多时,往往意味着后续步骤也需要重新操作。而使用数组公式,则可以一劳永逸地解决这个问题。

1
{=INDEX(A:A,SMALL(IF(MATCH(A$2:A$20,A$2:A$20,)=ROW($1:$19),ROW($2:$20),4^10),ROW(A1)))&""}

因为『删除重复项』本质上就是一个『输入一个数组,输出一个数组』的操作。在这个例子里,Match() 函数的第一个参数和两个 Row() 参数进行了相同的对应循环,并把每个计算结果填入相应的单元格里。

而另一个例子

1
{=Mid(A1,Row(1:100),1)}

则相当于把 A1 单元格中的每个字符都单拆出来。辅以其它公式嵌套,可以比较方便地计算诸如『若干个单元格一共包含多少个特定字符』之类的问题。

一句话总结:当你在使用 Excel 时,需要处理『处理若干个数据,过程中包含若干数据,结果也是若干个数据』时,在宏程序之外,还可以考虑使用数组公式。

一个需求:如何批量建立 Github 帐号下的库。

Github 库通常的建立方式是通过网页,其次是通过 Github 客户端 Publish。

但这两种方式都无法批量建立库,每新建一个库都需要用户重复操作一遍。

查了一下,还真有这样的办法。Github 提供了 Restful API 来帮助企业管理代码库。不光是批量建立,还包括添加删除用户组等等,非常完善。就建库这一需求,Github 提供了这样的一个 API:

https://developer.github.com/v3/repos/

第5节就讲的是如何 Create 一个库,提供了非常详尽的设置参数:

Name Type Description
name string Required. The name of the repository
description string A short description of the repository
homepage string A URL with more information about the repository
private boolean Either true to create a private repository, or false to create a public one. Creating private repositories requires a paid GitHub account. Default: false
has_issues boolean Either true to enable issues for this repository, false to disable them. Default: true
has_wiki boolean Either true to enable the wiki for this repository, false to disable it. Default: true
has_downloads boolean Either true to enable downloads for this repository, falseto disable them. Default: true
team_id integer The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization.
auto_init boolean Pass true to create an initial commit with empty README. Default: false
gitignore_template string Desired language or platform .gitignore template to apply. Use the name of the template without the extension. For example, “Haskell”.
license_template string Desired LICENSE template to apply. Use the name of the template without the extension. For example, “mit” or “mozilla”.

当然其中大部分参数可以忽略,理论上只有库名是必须的。

所以使用以下命令就可以在不登录网站或者客户端的前提下建立一个库,通过 Sublime Text 等多行文本编辑软件(甚至通过 Excel)编辑一个多行批处理文件,然后运行即可:

1
2
3
4
5
curl -u "Github用户名:Github密码" https://api.github.com/user/repos -d '{"name":"库一名字"}'
curl -u "Github用户名:Github密码" https://api.github.com/user/repos -d '{"name":"库二名字"}'
curl -u "Github用户名:Github密码" https://api.github.com/user/repos -d '{"name":"库三名字"}'
curl -u "Github用户名:Github密码" https://api.github.com/user/repos -d '{"name":"库四名字"}'
curl -u "Github用户名:Github密码" https://api.github.com/user/repos -d '{"name":"库五名字"}'

库名重复时,Github 会自动报错,并不影响批处理继续执行。

#Update:

改进了。现在的样式如下:

0

第一步,先做一张报销单:

从自动化的角度来说,尽量采用公式帮助计算、限定单元格可输入的内容、以及设置单元格格式。在这张单据里,编号单元格为 K1

公式:

对于报销单而言,使用 =SUM() 和 =VLOOKUP() 通常就足够了,至多再加个 =SUMIF()、=COUNTIF() 就足以做出挺复杂的报销单了。

单元格格式:

选定单元格后 『右键→设置单元格格式』。标准的可以选择第三类货币格式,复杂的可以自行定义格式,使用#代表一个数位,使用0代表『当这个数位是最高位但为0时依然显示』。

step1-2

限定填充序列:

选定单元格后菜单栏选择『 数据→数据验证→数据验证』。允许序列,来源直接写入需要的内容,用英文逗号分隔。

step1-3

第二步,添加 Excel 的开发工具菜单:

依次点击菜单上的 『文件→选项→(跳出 Excel 选项窗口)→自定义功能区→☑开发工具』打钩。

step2

第三步,设置打印宏:

点击菜单上的 『开发工具→Visual Basic』,打开 VBA 面板,左侧双击 『ThisWorkbook』,把以下代码粘贴到出现的窗口内,然后关闭窗口

注意 K1 为这篇文章中的编号位置,其它表单需要相应调整。

1
2
3
4
5
6
7
8
9
Sub PrintWithNumber()                                       '定义宏名
Dim startnum, loopnum, N As Long '定义变量:起始编码,打印份数和循环值
loopnum = Application.InputBox(Prompt:="需要打印多少份?") '定义打印份数
startnum = Sheet1.Range("K1") '读入表格上的份数的起始值
For N = startnum To startnum + loopnum - 1 '开始循环
ActiveSheet.PrintOut '打印当前表格
Range("K1") = N + 1 '份数加一
Next N '下一个循环直到结束
End Sub '结束

step3

第四步,添加宏按钮:

点击『开发工具→插入→按钮(窗体按钮)』。

step4

然后用鼠标在 Excel 空白处拖出一个方块,当松开鼠标时,会自动跳出『指定宏』窗口,选择窗口内的『ThisWorkbook.PrintWithNumber』,然后确定。

step4-2

右键点击该按钮,选择『编辑文字』,修改为『打印报销单』。

step4-3

第五步,设置打印区域:

这一步是为了防止把按钮本身也打印出来。

全选需要打印的区域,选择菜单 『页面布局→打印区域→设置打印区域』。

step5

第六步,另存为 xlsm:

由于使用了 vba,必须把文件存为 xlsm 格式。(启用宏的 Excel 格式)

完工。


今天接到一个小任务,寥寥一记。

在 Excel 中,常见的一种需求是打印带份数号码的各种表单,例如报销单、外出单等。通常财务都会提供模板给员工自行填写,再由财务按入帐顺序统一写上序号。但当某人一次性要写几十份,或者说类似的需求,需要一次性打印 N 份时,有没有办法让打印的表格上自动带上序号?

解决办法需要依赖 Excel 中的宏程序,在 Excel 中按 Alt+F11 可以直接打开宏编辑器。或需要先通过『视图』→『宏』→『录制宏』,再经由编辑宏的办法来打开。

核心宏程序如下,一目了然:

1
2
3
4
5
6
7
Sub test()
Dim N As Integer
For N = 1 To 10
Range("E1") = N
ActiveSheet.PrintOut
Next N
End Sub

E1 为需要填序号的单元格。程序先定义一个变量用来作为页码,然后不断用它替换指定单元格中的值,每替换一次就打印一张。这一方法硬要说有什么缺点的话,大概也就是打印任务数比较多,可能在几千份时会占用不少内存。

更完整的模板还需要在界面上做个按钮和两个输入框,以便让完全没有宏能力的财务也能定义起始和结束页码并打印。但今天这需求仅仅是帮助打印而不是做个新模版,所以这任务也就完成了不再搞复杂了。

样例下载 模板-日常费用报销表

Chrome 在更新到 44.0.2403.125 m 后,存在一个由拼写检查导致的性能低下 bug,该 bug 只在 win 版 Chrome 下呈现,同时影响 32 位和 64 位版本。

chrome-44-about就是这货

具体表现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
p {margin: 20px;font-weight: bold;text-align: center;width: 33%}
.input {display: block;width: 33%;margin: 20px;border: 2px solid #999;}
.editor {display: block;width: 33%;border-radius: 4px;margin:20px;overflow: scroll;padding: 8px;min-height: 100px;max-height: 400px;}
.area {border: 2px solid #fa0;}
.div {border: 2px solid #0af;}
</style>
</head>
<body>
<input type="text" class="input">
<p>Textarea</p>
<textarea class="editor area"></textarea>
<p>Contenteditable DIV</p>
<div class="editor div" contenteditable='true' role='textbox'></div>
</body>
</html>

将上面这段代码另存为 html 网页,在 Chrome 44 (win) 版本下打开。

用文本编辑器制造 10000 行会被触发单词拼写识别的文本,比如使用 Excel 连续生成 10000 行『AKB0048』。复制粘贴到橙色 Textarea 框中,然后用鼠标点击灰色 Input 框……

你会发现,非常的卡,光标在三个输入框中切换,每次切换都需要花费很长时间,对于性能不佳的电脑,和彻底进入死循环没区别了。

刷新页面重置数据后,再将这 10000 行粘贴到 Contenteditable DIV 的蓝色框里,第一次粘贴也略有卡顿,毕竟数据量比较大。但等卡顿过后,鼠标再在三个框中反复切换,就非常顺畅毫无迟滞感了。

10000linta

这就是这个 bug 的真身了:

在 Textarea 有大量会触发拼写检查的内容时,Chrome 44 的 Spellcheck 功能会极大消耗计算机资源,使得整台电脑近乎死机。

解决办法

由于这是浏览器 bug,前端程序员对此几乎无能为力,只能绕过这个 bug。

通常来说,HTML5 已经提出了 Textarea 的一些标准属性,比如 spellcheck=”false” 可以强制浏览器不检查内容,webkit 内核支持这一属性。正常来说,这似乎是很容易解决的一个兼容性问题。

但偏偏 Chrome 却强制忽略了这一设置,就像它强制忽略 font-size < 10 时那样。禁用拼写检查只在用户手动输入时有效,而对于 Ctrl+V 进来的内容,拼写检查依然正常运行,搞死你机。

即使你把相关属性全部列全:

1
<textarea class="editor area" spellcheck="false" autocapitalize="off" autocomplete="off" autocorrect="off"></textarea>

也是然并卵,在别的浏览器一切正常,而 Chrome 下依然故我。并没有解决问题。

解决方法一:

你可以通过 JS 检查当前浏览器是否是 Chrome,在需要粘贴大量内容的 textarea 上提示用户去关闭 SpellCheck 功能,具体位置为:

Chrome 菜单 → 设置 → (最下方)显示高级设置 → 语言和输入设置 → 启用拼写检查。

但这并不是一个好方法,尤其是需要用户主动去对 Chrome 进行设置。

解决方法二:

使用 JS,将一次的粘贴行为,模拟为连续字符添加的行为。比如当用户 Paste 后得到 Text 值,立刻删除该 Textarea 元素再重建一个。然后根据 text.length 使用 JQuery 插件 Jquery.Caret 不断循环插入字符。

这一方法缺点更多,首先是作为 walkaround 的方案,引入了太多并非用户参与的互动。其次,这一 bug 本来就是在大文本量 paste 下才会出现,如果再使用额外的一重循环,并不会使得体验有太多改善。最后,假如 Chrome 的再次升级把 JS 插入字符也纳入拼写检查的话,就会导致页面更 n 倍重的卡顿,到时候大概是再高性能的电脑都扛不住了。

解决方法三:

使用带 contenteditable=’true’ 属性的 DIV 元素代替 Textarea,并使用 innerText 或者 $.text() 来获取用户填写的文本内容。

10000lintv

这也是这篇博客所写的内容,这样的方法是最合法且绕过 Chrome 44 拼写检查 Bug 的方法。完全相当于是『有两种实现方法选择了另一种』。contenteditable = ‘true’ 属性的 DIV 往往也是很多 JS 版所见即所得编辑器的常用办法。比如 WordPress。这一方法不需要用户操作,也只需要少量 JS 代码。最后,即使这个 BUG 的影响范围继续蔓延,也不过是和现有的情况一样,不会更坏。

关于 MAC 版 Chrome:

Mac 下无此 bug,是因为暂时还没有拼写检查功能。

==== edit ====

现在 Mac 下也有了。

==== edit ====

现在修正了。

0%