Google方程式 WWWDOT – GOOGLE = DOTCOM
发布时间:2016-09-18, 17:47:29 分类:Linux | 编辑 off 网址 | 辅助
图集1/3
正文 11496字数 1,384,715阅读
有一个字符组成的等式:WWWDOT – GOOGLE = DOTCOM,每个字符代表一个0-9之间的数字,WWWDOT、GOOGLE和DOTCOM都是合法的数字,不能以0开头。请找出一组字符和数字的对应关系,使它们互相替换,并且替换后的数字能够满足等式。这个字符等式是Google公司能力倾向测试实验室的一道题目,这种题目主要考察人的逻辑推导能力和短期记忆能力,通常棋下的好的人解决这类问题会更得心应手一些(飞行棋例外)。此类型的题目有很多变种,各种编程比赛中常常能见到它们的身影。比如2005年的GOOGLE中国编程挑战赛第二轮淘汰赛有一道名为“SecretSum”的500分的竞赛题,与本题如出一辙,只不过字母都是三个,而且用的是加法计算。现在言归正传,先看看如何分析这个问题。以人的思维方式分析问题
将横式改成竖式可能更直观一些:
根据以上竖式减法,从左向右依次可以得到6个算式,分别是:
W – G = D (算式 1)
W – O = O (算式 2)
W – O = T (算式 3)
D – G = C (算式 4)
O – L = O (算式 5)
T – E = M (算式 6)
根据以上6个算式可以分析出两个关键信息:一个是W要足够大,因为考虑到它可能被借位的情况还要等于G和D的和;另一个则是本问题的突破口,就是算式2和算式3两次出现的W – O计算。现在分析算式2和算式3,根据是否需要借位,算式2和算式3一共有四种借位组合结果,下面分别对这四种借位组合结果进行分析。
1. W – O = T不需要借位,W – O = O也不需要借位
由于W – O = T和W – O = O都不需要借位,则可由算式2变形得到算式1.1:
W = 2O (算式1.1)
将算式1.1带入算式3,又可以得到算式1.2:
O = T (算式 1.2)
根据算式1.2,O和T代表的数字是同一个数字,这与题目要求不符,因此,这种借位组合不能得到正确的结果。
2. W – O = T需要借位,W – O = O不需要借位
根据借位情况,对算式2和算式3进行借位修正,得到两个修正算式:
W – 1 – O = O (算式2.1)
W + 10 – O = T (算式2.2)
由算式2.1变形得到算式2.3:
W = 2O + 1 (算式2.3)
将算式2.3带入算式2.2可以得到算式2.4:
T = O + 11 (算式2.4)
对算式2.3分析,由于W是个位数,最大值是9,所以O的取值只能是1-4,但是无论如何,由算式2.4计算出的T都超过9,这与题目要求不符,因此,这种情况也是无解的情况。
3. W – O = T不需要借位,W – O = O需要借位
根据借位情况,对算式2和算式3进行借位修正,得到两个修正算式:
W + 10 – O = O (算式3.1)
W – O = T (算式3.2)
由算式3.1变形得到算式3.3:
W = 2O – 10 (算式3.3)
将算式3.3带入算式3.2由可得到算式3.4:
O – 10 = T (算式3.4)
O显然是不能比10大的个位数,因此,这种情况也是无解的情况
4. W – O = T需要借位,W – O = O也需要借位
根据借位情况,对算式2和算式3进行借位修正,得到两个修正算式:
W – 1 + 10 – O = O (算式4.1)
W + 10 – O = T (算式4.2)
由算式4.1变形得到算式4.3:
W = 2O – 9 (算式4.3)
将算式4.3代入算式4.2得到算式4.4:
O + 1 = T (算式4.4)
由于W不能小于0,因此,根据算式4.3,O的取值最小为5。根据算式4.4继续分析,因为T不能大于9,因此O的最大值只能取值为8。根据O的取值区间[5,8],可依次计算出W和T的值,如下表所示:
已知O、W、T的取值,可以进一步推算其他字符代表的数字,上表中得到了四组目前合法的取值,但是并不是四组取值都能最终推算出正确的结果,本题的答案只有一个,也就是说只有一组O、W、T的取值是正确的,下面就分别进行分析。
O = 5, W = 1, T = 7
在这种情况下,考察算式1:W – G = D,W = 1显然无法满足此种情况,更何况算式2: W – O = O还要从它这里借位,因此,这种情况无解。
O = 6, W = 3, T = 7
在这种情况下,算式2: W – O = O还要从它这里借位,因此算式1:W – G = D对应的实际情况是2 – G = D,G和D不能同时为1,而且G和D都是第一位数字,不能是0,因此无法满足算式1,这种情况也是无解。
O = 7, W = 5, T = 8
在这种情况下,需要考察另另外两个关键算式,分别是算式5和算式6。根据这两个算式是否需要借位进行不同的假设,根据组合,仍然有四种假设,下面分别分析这四种假设:
假设一:算式5需要借位,算式6不需要借位。则此时算式5可修正为O + 10 – L = O,推算出L = 10,显然不符合题意,假设一不成立;
假设二:算式5需要借位,算式6需要借位,则算式5和算式6应该修正为算式4.3.1和算式4.3.2:
O -1 + 10 – L = O (算式4.3.1)
T + 10 – E = M (算式4.3.2)
因为已知T=8,带入4.3.2可得E+M=18,显然对于两个不相同的个位数无法满足这个等式,因此假设二也不成立;
假设三:算式5不需要借位,算式6不需要借位,此时根据算式6可知E和M的和是8(T=8),排除E=M=4的情况后,E和M的组合可以是(1,7)、(2,6)和(3,5),又因为数字5和7分别被W和O使用,因此E和M只能是2或6。再回头来看算式1,因为算式2需要借位,算式1实际相当于G + D = 4,G和D只能取值1和3,若G=1,D=3,则根据算式4计算出C=2,这与E或M矛盾。若G=3,D=1,则算式4需要借位,这又与算式3的假设矛盾。由此看来,假设三也不能得到正确的结果;
假设四:算式5不需要借位,算式6需要借位,此时根据算式5被修正为O – 1 – L = O,这种情况下也是无解的。
O = 8, W = 7, T = 9
在这种情况下,根据算式5和算式6是否借位的假设,仍然有四种假设,下面分别分析这四种假设:
假设一:算式5需要借位,算式6不需要借位。则此时算式5可修正为O + 10 – L = O,推算出L = 10,显然不符合题意,假设一不成立;
假设二:算式5需要借位,算式6需要借位,则算式5和算式6应该修正为算式4.4.1和算式4.4.2:
O -1 + 10 – L = O (算式4.4.1)
T + 10 – E = M (算式4.4.2)
因为已知T=9,带入4.4.2可得E+M=19,两个不同的个位数的和不可能大于18,因此假设二也不成立;
假设三:算式5不需要借位,算式6不需要借位,此时根据算式6可知E和M的和是9(T=9),E和M的组合可以是(1,8)、(2,7) 、(4,5)和(3,6),又因为数字8和7分别被O和W使用,因此E和M只能是(4,5)和(3,6)。进一步假设E=4,M=5(反过来E=5,M=4是一样的,不影响分析)。再看算式1,因为算式2需要借位,算式1实际相当于G + D = 6,由于M或E是5,所以G和D只能取值2和4。若G=2,D=4,则根据算式4计算出C=2,这与G=2矛盾。若G=4,D=2,则算式4需要借位,这又与算式3的假设矛盾,因此E=4,M=5的情况无解。再次进一步假设E=3,M=6(反过来E=6,M=3是一样的,不影响分析)。同样再看算式1,G和D的值可取是(2,4)和(1,5),G和D取值1和2的情况刚刚分析过无解,因此G和D的取值只能是1和5,前面分析过,算式4没有借位,也就是说要保证D > G,因此,D=5,G=1,根据算式4计算出C=4,这样就得到了一组解:O = 8,W = 7,T = 9,D = 5,L = 0, G = 1,C = 4,E = 3/6,M = 6/3。最终的等式是:
777589 – 188103 = 589486
或
777589 – 188106 = 589483
假设四:算式5不需要借位,算式6需要借位,此时根据算式5被修正为O – 1 – L = O,这种情况下也是无解的。
完整的分析过程结束,得到了一组答案,事实上通过计算机穷举算法也只能得到这一组结果,下面就看看如何用计算机算法求解本题的答案
用计算机穷举所有的解
以上是用人的思维方式的解题过程,如果方法正确,加上运气好(三次假设都是正确的,避免在错误分支上浪费时间),两分钟内就可得到结果。但是考虑到更通用的情况,字母数字没有规律,也没有可供分析的入手点和线索,比如:
AAB – BBC = CCD
这样的问题,该什么方法解决呢?只能“猜想”,用穷举的方法试探每一种猜想,对每个字母和数字穷举所有可能的组合,直到得到正确的结果。当然,这样的力气活交给计算机做是最合适不过了。
1. 建立数学模型
要想让计算机解决问题,就要让计算机能够理解题目,这就需要建立一个计算机能够识别、处理的数学模型,首先要解决的问题就是建立字母和数字的映射关系的数学模型。本题的数学模型很简单,就是一个字母二元组:{char, number}。考察等式:
WWWDOT – GOOGLE = DOTCOM
共出现了9个不同的字母:W、D、O、T、G、L、E、C和M,因此,最终的解应该是9个字母对应的字母二元组向量:[ {‘W’, 7}, {‘D’, 5}, {‘O’, 8}, {‘T’, 9}, {‘G’, 1}, {‘L’, 0}, {‘E’, 3}, {‘C’, 4}, {‘M’, 6} ]。穷举算法就是对这个字母二元组向量中每个字母二元组的number元素进行穷举,number的穷举范围就是0-9共10个数字,当然,根据题目要求,有一些字符不能为0,比如W、G和D。排列组合问题的穷举多使用多重循环,看样子这个穷举算法应该是9重循环了,在每层循环中对一个字母进行从0到9遍历。问题是,必须这样吗,对于更通用的情况,不是9个字母的问题怎么办?首先思考一下是否每次都要遍历0-9。题目要求每个字母代表一个数字,而且不重复,很显然,对每个字母进行的并不是排列,而是某种形式的组合,举个例子,就是如果W字母占用了数字7,那么其它字母就肯定不是7,所以对D字母遍历是就可以跳过7。进一步,假设某次遍历的字母二元组向量中除M字母外其它8个字母已经有对应的数字了,比如:
[ {‘W’, 7}, {‘D’, 5}, {‘O’, 8}, {‘T’, 9}, {‘G’, 1}, {‘L’, 0}, {‘E’, 3}, {‘C’, 4}, {‘M’, ?} ] (序列-1)
那么M的可选范围就只有2和6,显然没必要使用9重循环。
现在换一种想法,对9个二元组的向量进行遍历,可以分解为两个步骤,首先确定第一个二元组的值,然后对剩下的8个二元组进行遍历。显然这是一种递归的思想(分治),算法很简单,但是要对10个数字的使用情况进行标识,对剩下的二元组进行遍历时只使用没有占用标识的数字。因此还需要一个标识数字占用情况的数字二元组定义,这个二元组可以这样定义:{number, using},0-9共有10个数字,因此需要维护一个长度为10的数字二元组向量。数字二元组向量的初始值是:
[{0, false}, {1, false},{2, false},{3, false},{4, false},{5, false},{6, false},{7, false},{8, false},{9, false}] (序列-2)
每进行一重递归就有一个数字的using标志被置为true,当字母二元组向量得到(序列-1)的结果时,对应的数字二元组向量的值应该是:
[{0, true}, {1, true},{2, false},{3, true},{4, true},{5, true},{6, false},{7, true},{8, true},{9, true}] (序列-3)
此时遍历这个数字二元组向量就可以知道M字母的可选值只能是2或6。
穷举遍历的结束条件是每层递归中遍历完所有using标志是false的数字,最外一层遍历完所有using标志是false的数字就结束了算法。
根据题目要求,开始位置的数字不能是0,也就是W、G和D这三个字母不能是0,这是一个“剪枝”条件,要利用起来,因此,对字母二元组进行扩充成字母三元组,添加一个leading标志:{char, number, leading}。下面就是这个数学模型的C语言定义:
typedef struct
{
char c;
int value;
bool leading;
}CharItem;
typedef struct
{
bool used;
int value;
}CharValue;
Run code
Cut to clipboard
根据此数学模型初始化字母三元组和数字二元组向量:
CharItem char_item[max_char_count] =
{
{ 'W', -1, true }, { 'D', -1, true }, { 'O', -1, false },
{ 'T', -1, false }, { 'G', -1, true }, { 'L', -1, false },
{ 'E', -1, false }, { 'C', -1, false }, { 'M', -1, false }
};
CharValue char_val[max_number_count] =
{
{false, 0}, {false, 1}, {false, 2}, {false, 3},
{false, 4}, {false, 5}, {false, 6}, {false, 7},
{false, 8}, {false, 9}
};
Run code
Cut to clipboard
2. 穷举算法
建立数学模型,其实就是为了让计算机理解题目并处理相关的数据,算法就是告诉计算机如何使用这些模型中的数据。本文介绍的是穷举算法,算法的核心其实前面已经提到了,就是穷举所有的字母和数字的组合,对每种组合进行合法性判断,如果是合法的组合,就输出结果。
整个算法的核心是SearchingResult()函数,其实这个函数非常简单:
void SearchingResult(CharItem ci[max_char_count],
CharValue cv[max_number_count],
int index, CharListReadyFuncPtr callback)
{
if(index == max_char_count)
{
callback(ci);
return;
}
for(int issi = 0; issi < max_number_count; ++issi)
{
if(IsValueValid(ci[index], cv[issi]))
{
cv[issi].used = true;/*set used sign*/
ci[index].value = cv[issi].value;
SearchingResult(ci, cv, index + 1, callback);
cv[issi].used = false;/*clear used sign*/
}
}
}
Run code
Cut to clipboard
SearchingResult()函数有四个参数,ci就是存储遍历结果的字母三元组向量,cv是存储遍历过程中数字占用情况的数字二元组向量,index是当前处理的字母三元组在字母三元组向量中的位置索引,0表示第一个字母三元组。callback是一个回调函数,当ci中所有三元组都分配了数字,就调用callback对这组解进行判断,如果满足算式就输出结果。SearchingResult()函数的代码分两部分,前一部分是结束条件判断和结果输出,后一部分是算法的关键。算法就是遍历cv中的所有数字二元组,对于每一个可用的数字(当前没有被占用,并且满足第一个数字不是0的要求),首先设置占用标志,然后将当前字母三元组的值与这个数字的值绑定,最后递归处理下一个字母三元组。
SearchingResult()函数是一个通用过程,负责字母和数字的组合,回调函数(callback)负责根据题目要求对SearchingResult()函数得到的字母和数字的组合进行筛选,只输出正确的组合。对于本题,回调函数可以这样实现:
void OnCharListReady(CharItem ci[max_char_count])
{
char *minuend = "WWWDOT";
char *subtrahend = "GOOGLE";
char *diff = "DOTCOM";
int m = MakeIntegerValue(ci, minuend);
int s = MakeIntegerValue(ci, subtrahend);
int d = MakeIntegerValue(ci, diff);
if((m - s) == d)
{
std::cout << m << " - " << s << " = " << d << std::endl;
}
}
Run code
Cut to clipboard
3. 结果验证
根据char_item和char_val的初始数据,求解本题的Google方程式:
SearchingResult(char_item, char_val, 0, OnCharListReady);
穷举算法可以得到两个结果(M和E可以互换):
777589 – 188103 = 589486
777589 – 188106 = 589483
由于算法具有通用性,对于前文例子中的等式:
AAB – BBC = CCD
只需要构造新的字母三元组向量,并修改回调函数的过滤数据即可。新的字母三元组可按照如下方式构造:
CharItem char_item[max_char_count] = { {'A', -1, true}, {'B', -1, true}, {'C', -1, true},
{'D', -1, false} };
Run code
Cut to clipboard
回调函数与前文的OnCharListReady()函数类似,此处不再列出。根据新的字符三元组和回调函数运行算法,可以得到13组结果:
443 – 331 = 112
553 – 332 = 221
554 – 441 = 113
665 – 551 = 114
774 – 443 = 331
775 – 552 = 223
776 – 661 = 115
885 – 553 = 332
886 – 662 = 224
887 – 771 = 116
995 – 554 = 441
997 – 772 = 225
998 – 881 = 117
对于加法、乘法和除法算式,同样只要使用不用的回调函数进行结果判断即可,不需要修改SearchingResult()函数,例如加法算式:
ABC + ABC = BCE
可以得到5组结果:
124 + 124 = 248
125 + 125 = 250
249 + 249 = 498
374 + 374 = 748
375 + 375 = 750
PHP 数组元素所有组合穷举解决方案
<?php
/*
有一个字符组成的等式:WWWDOT – GOOGLE = DOTCOM,每个字符代表一个0-9之间的数字,WWWDOT、GOOGLE和DOTCOM都是合法的数字,不能以0开头。请找出一组字符和数字的对应关系,使它们互相替换,并且替换后的数字能够满足等式。
*/
// WWWDOT
$t1 = microtime(true);
// ... 执行代码 ...
//php 解决方案 通过数组内所有元素所有排序组合穷举所有结果
$source = array('w','d','o','t','g','l','e','c','m','x');//加x元素保证有0-9个数字
//$source = array('x','w','d','o','t','g','l','e','c','m');
sort($source); //保证初始数组是有序的
$last = count($source) - 1; //$source尾部元素下标
$x = $last;
$count = 1; //组合个数统计
//echo implode(',', $source), "<br>"; //输出第一种组合
echo ss($source);
if(ss($source)){
echo implode(',', $source), "<br>"; //输出第一种组合
return true;
}
function ss($array){
//return 'asss';
$w=array_search('w', $array);
$d=array_search('d', $array);
$o=array_search('o', $array);
$t=array_search('t', $array);
$g=array_search('g', $array);
$l=array_search('l', $array);
$e=array_search('e', $array);
$c=array_search('c', $array);
$m=array_search('m', $array);
$wwwdot=$w.$w.$w.$d.$o.$t;
$google=$g.$o.$o.$g.$l.$e;
$dotcom=$d.$o.$t.$c.$o.$m;
//return $wwwdot.'='.$google.'+'.$dotcom;
$sr=$google+$dotcom;
if($sr==$wwwdot){
//echo 1111;
return $wwwdot.'='.$google.'+'.$dotcom;
}
return false;
}
while (true) {
$y = $x--; //相邻的两个元素
if ($source[$x] < $source[$y]) { //如果前一个元素的值小于后一个元素的值
$z = $last;
while ($source[$x] > $source[$z]) { //从尾部开始,找到第一个大于 $x 元素的值
$z--;
}
/* 交换 $x 和 $z 元素的值 */
list($source[$x], $source[$z]) = array($source[$z], $source[$x]);
/* 将 $y 之后的元素全部逆向排列 */
for ($i = $last; $i > $y; $i--, $y++) {
list($source[$i], $source[$y]) = array($source[$y], $source[$i]);
}
//echo implode(',', $source), "<br>"; //输出组合
$srrr=ss($source);
if($srrr){
echo $srrr.'<br />';
//return true; 不退出获取所有可能组合
}
$x = $last;
$count++;
}
if ($x == 0) { //全部组合完毕
break;
}
}
//echo 'Total: ', $count, "\n";
$t2 = microtime(true);
echo '<br />耗时'.round($t2-$t1,3).'秒';
/*这个循环好像是错的,到崩溃都不能出结果
for($w=1;$w<10;$w++){
for($d=1;$d<10;$d++){
for($o=0;$o<10;$o++){
for($t=0;$t<10;$t++){
for($g=0;$g<10;$g++){
for($l=0;$l<10;$l++){
for($e=0;$e<10;$e++){
for($c=0;$c<10;$c++){
for($m=0;$m<10;$m++){
echo $i++.'<br>';
$wwwdot=$w.$w.$w.$d.$o.$t;
$google=$g.$o.$o.$g.$l.$e;
$dotcom=$d.$o.$t.$c.$o.$m;
if($wwwdot==($google+$dotcom)){
echo '<br>'.$wwwdot.'<br>'.$google.'<br>'.$dotcom;
return true;
}
}
}
}
}
}
}
}
}
}*/
Run code
Cut to clipboard
运行结果:
原文出处: oRbIt 译文
(支付宝)给作者钱财以资鼓励 (微信)→
有过 16 条评论 »
本文实例讲述了php求数组全排列,元素所有组合的方法。分享给大家供大家参考,具体如下:
<?php $source = array('pll','我','爱','你','嘿'); sort($source); //保证初始数组是有序的 $last = count($source) - 1; //$source尾部元素下标 $x = $last; $count = 1; //组合个数统计 echo implode(',', $source), "<br>"; //输出第一种组合 while (true) { $y = $x--; //相邻的两个元素 if ($source[$x] < $source[$y]) { //如果前一个元素的值小于后一个元素的值 $z = $last; while ($source[$x] > $source[$z]) { //从尾部开始,找到第一个大于 $x 元素的值 $z--; } /* 交换 $x 和 $z 元素的值 */ list($source[$x], $source[$z]) = array($source[$z], $source[$x]); /* 将 $y 之后的元素全部逆向排列 */ for ($i = $last; $i > $y; $i--, $y++) { list($source[$i], $source[$y]) = array($source[$y], $source[$i]); } echo implode(',', $source), "<br>"; //输出组合 $x = $last; $count++; } if ($x == 0) { //全部组合完毕 break; } } echo 'Total: ', $count, "\n";
更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP数组(Array)操作技巧大全》、《PHP数学运算技巧总结》、《php正则表达式用法总结》、《PHP+ajax技巧与应用小结》、《PHP运算与运算符用法总结》、《PHP网络编程技巧总结》、《PHP基本语法入门教程》、《php日期与时间用法总结》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。
解决问题:求一个含有N个元素的数组中取出M个元素组成新的数组,一共可以组合成的数组并输出
<?php $arr = array('a','b','c','d'); $result = array(); $t = getCombinationToString($arr, 4); print_r($t); function getCombinationToString($arr, $m) { if ($m ==1) { return $arr; } $result = array(); $tmpArr = $arr; unset($tmpArr[0]); for($i=0;$i<count($arr);$i++) { $s = $arr[$i]; $ret = getCombinationToString(array_values($tmpArr), ($m-1), $result); foreach($ret as $row) { $result[] = $s . $row; } } return $result; }
$t1 = microtime(true); // ... 执行代码 ... $t2 = microtime(true); echo '耗时'.round($t2-$t1,3).'秒';
简单说一下. microtime() 如果带个 true 参数, 返回的将是一个浮点类型. 这样 t1 和 t2 得到的就是两个浮点数, 相减之后得到之间的差. 由于浮点的位数很长, 或者说不确定, 所以再用个 round() 取出小数点后 3 位. 这样我们的目的就达到了~
前端语言 浏览器 JavaScript算法
<script> var mycars = new Array() //加x元素保证有0-9个数字 mycars[0] = "w" mycars[1] = "d" mycars[2] = "o" mycars[3] = "t" mycars[4] = "g" mycars[5] = "l" mycars[6] = "e" mycars[7] = "c" mycars[8] = "m" mycars[9] = "x" permutate(mycars); function sff(s,v){ var u=s.indexOf(v); if(u!='-1') return u.toString(); else return false; } function permutate(array,permutatedArray){ if(!permutatedArray){ permutatedArray = []; } if(array.length > 1){ //弹出第一个数 var elementCur = array.shift(); //排列剩余的数组 permutate(array,permutatedArray); //返回剩余的数组的排列长度 var permutatedArrayLen = permutatedArray.length; //第一个数与其他剩余数组所有数组组合 for(var j = 0;j < permutatedArrayLen; j++){ //弹出不齐的组 var p = permutatedArray.shift(); //把当前元素放到排列好的数组的所有位置 for(var i = 0; i <= p.length; i++){ //复制排列好的数组 var r = p.slice(0); //插入数据到数组的位置 r.splice(i, 0, elementCur); //保存 permutatedArray.push(r) //console.log(r);return false; if(r.length==10) { var w=sff(r,'w'); var d=sff(r,'d'); var o=sff(r,'o'); var t=sff(r,'t'); var g=sff(r,'g'); var l=sff(r,'l'); var e=sff(r,'e'); var c=sff(r,'c'); var m=sff(r,'m'); //WWWDOT – GOOGLE = DOTCOM var wwwdot=parseInt(w+w+w+d+o+t); var google=parseInt(g+o+o+g+l+e); var dotcom=parseInt(d+o+t+c+o+m); var nnnwwwwdot=google+dotcom; if(wwwdot==nnnwwwwdot){ console.log(wwwdot+'='+google+'+'+dotcom); //return true; } } //console.log(r); } } //退出条件 }else{ permutatedArray.push([array[0]]); } return permutatedArray; } </script>
parseInt('123') : 返回 123(int); parseInt('1234xxx') : 返回 1234(int);
parseInt(string) : 函数从string的开始解析,返回一个整数。
如果解析不到数字,则将返回一个NaN的值,可以用isNaN()函数来检测;
var i = parseInt('abc'); if (isNaN(i)) { alert('NaN value'); }
同样的parseFloat函数是将字符串转换成浮点数。
举例:
parseFloat('31.24abc') : 返回 31.24;
js数字转换成字符串
将字符串转换成数字,得用到String类的toString方法
var i = 10; var s = i.toString(); alert(typeof s); //将输出 String
js数字与字符串的区别
js的数字的加法与字符串的连接都是 + 符号, 所以究竟是加还是字符串的连接就取决与变量的类型。
var a = 'abc' + 'xyz'; //a的值为:abcxyz,字符串与字符串是连接 var a = 10 + 5; //a的值为:15,数字是加 var a = 'abc' + 10; //a的值为:abc10,字符串与数字,自动将10转换成字符串了 var a = 'abc' + 10 + 20 + 'cd'; //a的值为:abc1020cd var a = 10 + 20 + 'abc' + 'cd'; //a的值为:30abccd,可以数字加的先数字加,然后再连接
如果从html页面元素得到的值,想按数字加,就需要先转换为数字,因为从页面得到的值默认是字符串。
function permutate(array,permutatedArray){ if(!permutatedArray){ permutatedArray = []; } if(array.length > 1){ //弹出第一个数 var elementCur = array.shift(); //排列剩余的数组 permutate(array,permutatedArray); //返回剩余的数组的排列长度 var permutatedArrayLen = permutatedArray.length; //第一个数与其他剩余数组所有数组组合 for(var j = 0;j < permutatedArrayLen; j++){ //弹出不齐的组 var p = permutatedArray.shift(); //把当前元素放到排列好的数组的所有位置 for(var i = 0; i <= p.length; i++){ //复制排列好的数组 var r = p.slice(0); //插入数据到数组的位置 r.splice(i, 0, elementCur); //保存 permutatedArray.push(r) } } //退出条件 }else{ permutatedArray.push([array[0]]); } return permutatedArray; }
function sureDay(year,month){ return (new Date(year,month,0)).getDate() }
function isLeapYear(year){ return (new Date(year,2,0)).getDate()==29; }
起因:关于数据类型这块,自己看了很多遍相关的资料,每次查看和实践都有一些体会和理解;但又感到没有理解透,总是差一点,最近又在看这块的内容,加上最近的积累,做个相关笔记
ECMAScript数据类型:
1. 5中简单数据类型:String Number Boolean Undefined Null
2. 1种复杂数据类型:Object,本质是一组无序的名值对组成的,eg:Array JSON ...
【理解】对于JS数据方面的操作,都是数据类型之间的转换和操作,只要针对的攻克每一种数据类型,在逐步的融合,JS水平会有一个很好的进步;
typeof操作符
1. 这是个操作符,不是方法
2. 之所以typeof存在,是因为ECMAScript是松散类型的语言;松散类型就是变量可以是任意数据类型,可以任意转换(不推荐)
typeof(String) => string => 如果这个值是字符串 typeof(Number) => number => 如果这个值是数值 typeof(Boolean) => boolean => 如果这个值是布尔值 typeof(Undefined) => undefined => 如果这个值未定义 typeof(Object) => object => 如果这个值是对象或null typeof(Function) => function => 如果这个值是函数
一、 Undefined类型
当【声明】一个变量,但是【未初始化】,这个变量的值就是undefined
一直以来的困惑:
1. 对【未初始化】的变量执行typeof操作符,返回undefined值
2. 对【未声明】的变量执行typeof操作符,返回undefined值
var message; console.log(typeof message); // undefined console.log(typeof age); // undefined
困惑:导致自己一直不知道该怎么解决这个问题,书上标注的解决办法是:显式的使用undefined来给没有初始化的变量进行赋值,每次实践的结果和书上说的有出入
感悟:自己刚刚结合了jQuery上的$.type()的工具函数,和自己写的一些例子
var message; // jQuery中$.type()工具函数 console.log($.type(message)); // undefined console.log($.type(age)); // 【报错】age is not defined // 自己理解写的例子 console.log(message==undefined); // true console.log(age==undefined); // 【报错】age is not defined
所以,无论从$.type()的角度看,验证结果;还是从例子中查看结果,都可以看出,对于【未声明】和【未初始化】分离和验证都不是难题;
【注】对于$.type()的原理实现,是否是我例子中的方法,我还没有验证;当然这不是重点,重点是,妈妈再也不担心我分不清【未声明】和【未初始化】了;
【项目中】在实际的项目中,肯定是不允许有报错行为的,这样大大的影响了程序的进一步运行;所以,用下面这种方式:
var message; // jQuery中$.type()工具函数 console.log($.type(message)); // undefined try{ console.log($.type(age)); // 不报错了 }catch(e){ console.log("age is not defined!"); }; // 自己理解写的例子 console.log(message==undefined); // true try{ console.log(age==undefined); // 不报错了 }catch(e){ console.log("age is not defined!"); };
二、Null类型
1.从逻辑的角度,null值表示一个空对象指针
2.typeof(null),返回object
3.如果定义的变量未来准备用来保存对象,最好将其初始化成null
只要检测出来不是null就可以进行下一步操作:
if(ele != null){ //要执行的代码 }
4.undefined值是派生自null值,因此:console.log(undefined == null); //true
console.log(undefined == null); // true // 从JS角度 console.log(typeof undefined); // undefined console.log(typeof null); // object // 从jQuery角度 console.log($.type(undefined)); // undefined console.log($.type(null)); // null
三、Boolean类型
1.有两个字面量:true and false
2.区分大小写,只有全小写形式,属于Boolean类型,其余的只是标识符
3.转型函数Boolean(),将任意类型的字符转换成Boolean类型
转换规则:
数据类型 => true => false
String类型 => 任意非空字符串 => ""(空字符串) Number类型 => => 任意非零数字值(包括无穷大) => 0和NaN Boolean类型 => true => false Object类型 => 任意对象 => null Undefined类型 => n/a(or N/A),意思是不适用(not applicable) => undefined
四、Number类型
1.数值字面量表示方式:十进制、八进制(严格模式不支持,直接报错)、十六进制
八进制:第一位必须是0,然后是八进制数字序列(0~7)
十六进制:前两位必须是0x,后跟十六进制数字序列(0~9及A~F),字母(A~F)大小写都可以
算术计算时:所有以八进制和十六进制表示的数值最终都将被转换成十进制数值
正零 == 负零(+0 == -0)
2.浮点数值
就是数值中包含一个小数点,小数点后必须至少有一位数字
小数点前面可以没有整数,但是不推荐(.1)
保存浮点数值所需的内存空间是保存整数的两倍,所以下面这些浮点数,会当做整数处理
1. => 1 10.0 => 10
对于极大极小的数值,可以用e表示法(即科学计数法)来表示浮点数值;e前面的数值*10的指数次幂,幂是e后面的数值
3.125e7 == 31250000 0.00000000000000003 == 3e-17
默认情况下,ECMAScript会将那些小数点后面带有6个零以上的浮点数值转换成e表示法
浮点数值的最高精度是17位小数,但在进行算数计算时其精确度远远不如整数
0.1 + 0.2 != 0.3 0.1 + 0.2 != 0.30000000000000004
【注】浮点数值计算有舍入误差,其它基于IEEE754数值的浮点数计算语言都有这类通病
3.数值范围
由于内存的限制,ECMAScript不能保存世界上所有的数值
最小值:Number.MIN_VALUE 最大值:Number.MAX_VALUE
最值具体等于多少数值,不同的浏览器有不同的结果,具体以实际为准
数值计算结果超出最值范围,将被自动转换成特殊的正值是Infinity(正无穷)值,负值是-Infinity(负无穷)
判断某个数值是不是有穷数值(是不是位于最小值和最大值之间),可以使用isFinish()函数,结果是有穷的返回true,否则false
var num = Number.MIN_VALUE + Number.MAX_VALUE; console.log(num); // false
Infinity和-Infinity保存只
Number.POSITIVE_INFINITY == Infinity Number.NEGATIVE_INFINITY == -Infinity
4.NaN
NaN,即非数值(Not a Number)是一个特殊的数值,当数值计算出现错误的时候,返回NaN,如:任何数除以0会返回NaN,这样不影响其它代码的执行
两个特点:
--- 1.任何涉及NaN的操作(NaN/10)都会返回NaN,这个特性在多步计算中有可能导致问题
--- 2.NaN与任何值都不相等,包括NaN本身
console.log(NaN == NaN); // false
isNaN()函数,这个函数接收一个参数,该参数可以是任何类型;意思是是否【不是数值】
当参数不是数值时,返回true;当参数是数值时,返回false
console.log(isNaN("10")); // false console.log(isNaN("blue")); //true
isNaN()也适用于对象,首先调用对象的valueof()方法=?是否可以转换为数值,如果不能,在调用toString()方法