Windows计算器算法分析(标准型)

本文详细分析了Windows计算器标准型的算法,包括四则运算、一元运算符、百分比运算、归零键、退格键以及临时存储功能等。通过一系列的例子,揭示了按键功能的工作原理和运算过程,例如[=]键的运算规则,四则运算符的执行条件,以及[BK]键如何处理数字格式。此外,还讨论了[粘贴]功能的特殊性和显示格式的细节,如小数点的位置和[BK]键删除数字后的显示变化。通过这些分析,有助于理解Windows计算器的内部机制,并为仿制计算器提供指导。
摘要由CSDN通过智能技术生成

 

(如果您在本文中发现有错别字或明显笔误,请留言指出,如确实有错我将尽快更正,谢谢。)

说起计算器,从小学起就开始用了吧,不过要说研究应该是初中时。简单地说就是学会了四个M键的用法,更进一步地说发现了许多有趣的组合键。对于我使用的那个计算器来说,最早发现的是同    时按下×、÷、-就会出现9,然后又发现同时按住×、÷再按ON就能关机,而同时按住×、÷时缓慢地按ON则无法开机,于是我做了大量的试验,又发现了许多类似的组合键。当然不同的计算器会有不同的效果,而科学计算器一般不会这样。我当时就在想到底是什么样的程序造成了这样的彩蛋呢?不过到现在这也还是个迷。

 

前两天在仿制Windows的计算器(以下简称W)时,发现它的算法和平时用的计算器也有很多不同,最明显的就是10020%并不是100*(1+20%)而是简单的100*20%。为了做到惟妙惟肖我进行的大量的分析。(注:以下分析均指W的标准型。)

 

为了便于之后的分析我们先来声明一些规则。对于二元运算需要有两个运算数和一个运算符,我们声明W有如下四个变量:左数变量右数变量符变量串变量,分别用于存储左数右数、运算符(专指四则运算符)和输入的数字字符串。当我们按下四则运算符时将把运算符存入符变量中,当我们输入数字或小数点时,数字将以字符串形式依次存入串变量中。我们称W显示的数字为当前数。至于每个名词的具体含义将在下文用到时给出。

1[12.3] 依次将12.3存入串变量(12.3)  [+]+存入符变量(12.3) [45.6] 依次将45.6存入串变量(45.6)  [=]计算12.3+45.6并显示结果(57.9) 

如例1所示,本文将使用“[按键名]”的形式来表示相应的按键或按下相应的按键,使用 [按键名] 并发操作(显示)”的格式来表示我们的按键过程及W的运行过程。其中“并发操作”和 “(显示)”有时根据需要会被省略或部分省略。对于连续的数字输入12.3我们将简单的表示为[12.3]而不是[1] [2][.] [3],并称其为一次运算数输入(“一次运算数输入”这一概念在下文中将得到扩展)。若无特别说明每例进行前都要对W进行归零,即[C](0.)

对于所有按键而言,如果其功能不能正确执行,则发出提示音,如在已[.]的基础上再次[.]

 

W提供了八种运算,我们可以将他们分为两类:一元运算[+/-][sqrt][1/x]和二元运算[+][-][*][/][%]。下面我们先来分析最基础的四则运算(即[+][-][*][/])。简单的来说四则运算就是我们想象中的样子,但通过下面的例子我们将会发现,他们也并非我们想象的那样简单。

2:[1](1.) [+](1.) [=](2.)

3:[+](0.) [1](1.) [=](1.)

四则运算需要两个运算数及一个运算符(下文若无说明,运算符均指四则运算符),在本文中我们将二元运算符的第一个运算数称为其左数,而第二个运算数称为其右数,并分别用左数变量右数变量存储这两个数。而例23中我们只输入了一个运算数和一个运算符便可以计算结果了。由此我们可以得到这样一个猜想:两个运算数均有初始值。那这个初始值是多少呢?在例11+=的结果是2,因此我们可以推断右数的初始值为1。同样的我们可以推断在例3中左数的初始值为0。而如果将这两例中的运算数1换作任意数n,那么我们不难发现例2中右数的初始值实际上是左数,而例3中左数的初始值始终是0

 

由此我们可以进一步猜想,在例2中,当我们[=]后,得出结果之前,W已经把我们输入的1同时赋给左右数变量。那这样的赋值运算又是什么时候完成的呢?首先不是[数字](此处理解为按下数字键,请根据语境理解下文中的“[]”格式)时完成的,否则在例3[1]之后左数也会变为1,而实际上左数为0。其次也不会是[=]时完成的,否则在例3中左数也会变成1,而首次[=]的结果就会变成2。因此赋值运算是在[+]时完成的。那么是不是每次[+]时都会执行这样的赋值运算呢?前面说,W把输入的数字赋给了左右数变量,而在例3中按+之前我们并没有输入任何数字,那么赋值运算是否执行了呢,如果执行了那是将什么数赋给了左右数变量了呢?这里为了简化思路我们不妨假想[+]时赋值运算总是执行的,并且是将当前数赋给了左右数变量。由此我们可以进一步假想左右数变量的初始值都是0,而当前数的初始值显然是0。事实上这两个假想与后面的分析并无矛盾。同理,我们分析[-][*][/]可以得到相同的结论,不同的只是将[+]换成了[-][*][/]

 

下面我们来分析[=]。由例23可以看出,[=]W计算了表达式 左数 运算符 右数 的结果并显示出来。我们再来看这样的例子:

4[3](3.) [*](3.) [10](10.) [=](30.) [=](300.) [=](3000.) [=](30000.)

5[3](3.) [*](3.) [10](10.) [=](30.) [=](300.) [11](11.) [=](3000.) [=](30000.)

在例4中,首次[=]计算的表达式应该是 3*10 ,因此结果为30。而根据后三次[=]的结果来看我们可以推测出后三次[=]计算的表达式分别为:30*10300*103000*10。因此我们不难想象,[=]W计算了表达式 左数 运算符 右数 的结果,并将其赋给左数变量同时显示出来。之前我们已经讨论过了左数变量是在按运算符后被赋值的,那么在例3和这两个例子中右数变量又是什么时候被赋值的呢?不难看出是在[数字]的同时或者是在[=]的同时进行的,那么到底是哪种情况呢?例5将帮助我们找到答案。例5是在例4的基础上多键入了一次数字11,但很明显,这并没有对后面的操作产生影响。如果说按数字键时会把当前数赋给右数变量,那么之后[=]应该得到3300而不是3000。可是同样的道理,如果[=]时进行的赋值,结果也应该是3300而不是3000啊,那赋值到底是怎样进行的呢?

 

我们再来仔细分析一下例5。在例5中,右数变量可能被赋值的地方有两处,一是[10][=],二是[11][=],那么为什么在第一处将10赋给了右数,而第二处却没有将11赋给右数变量呢?仔细比较我们就会发现它们的区别,第一处的前次是[*],即运算符。而第二处的前次是[=],即非运算符。如果我们称[运算符]后紧接的一次运算数输入为一次有效的右数输入的话,那么当一次有效的右数输入后[=]就把当前数赋给右数变量,否则不进行赋值。这样一来我们又回到了一开始的问题:是在[数字]时还[=]时,才把当前数赋给右数变量的呢?我们先来假设是在[=]时进行赋值的。这样对于例5

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值