使用循环实现斐波那契数列

递归中比较常见的例子是斐波那契数列、汉诺塔。

使用递归实现斐波那契数列其实很浪费,f(n) = f(n-1) + f(n-2)。在进一步计算 f(n-1) = f(n-2) + f(n-3),会发现 f(n-2) 被重复计算。

下面是通过循环实现的斐波那契数列:

function Fibonacci(number) {
	var i, list = new Array();

	list[0] = 0;
	list[1] = 1;

	for (i = 1; i < number; i++) {
		list[i + 1] = list[i] + list[i - 1];
	}

	return list[number];
}

获取完整的斐波那契数列:

function Fibonacci(number, full) {
	var i, list = new Array();

	list[0] = 0;
	list[1] = 1;

	for (i = 1; i < number; i++) {
		list[i + 1] = list[i] + list[i - 1];
	}

	if (full) {
		return list;
	}

	return list[number];
}

JavaScript Crypto-JS 使用手册

使用 Crypto-JS 可以非常方便地在 JavaScript 进行 MD5、SHA1、SHA2、SHA3、RIPEMD-160 哈希散列,进行 AES、DES、Rabbit、RC4、Triple DES 加解密。

基于 Crypto-JS 实现的在线加密解密工具 —— 在线哈希、在线散列 和 在线加密、在线解密

下面讲述如何使用 Crypto-JS。

Crypto-JS 源码托管在 Google Code,当前版本是 3.1。因为一般在国内也无法打开,所以把源代码分享到百度盘:http://pan.baidu.com/s/1bnyIGxT

Crypto-JS 原网址是 https://code.google.com/p/crypto-js/文中的英文描述均是原作者所有,Crypto-JS 采用的授权协议跟 MIT 类似,可以在任何场景放心使用。

文章最末附上 Crypto-JS 文件目录结构。

使用 Crypto-JS 进行哈希、散列

  • md5

引入 md5.js

<script src="cryptojs/rollups/md5.js"></script>

调用 md5 方法

var str = '123456';
CryptoJS.MD5(str);
  • pbkdf2

PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can’t be used directly as a cryptographic key, some processing is required.

A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.

引入 pbkdf2.js

<script src="cryptojs/rollups/pbkdf2.js"></script>

调用 pbkdf2 方法

// 官方示例
var str = '123456';
var salt = CryptoJS.lib.WordArray.random(128/8);

var key128Bits = CryptoJS.PBKDF2(str, salt, { keySize: 128/32 });
var key256Bits = CryptoJS.PBKDF2(str, salt, { keySize: 256/32 });
var key512Bits = CryptoJS.PBKDF2(str, salt, { keySize: 512/32 });

var key512Bits1000Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, {
keySize: 512/32,
iterations: 1000
});
  • ripemd160

引入 ripemd160.js

<script src="cryptojs/rollups/ripemd160.js"></script>

调用 ripemd160 方法

var str = '123456';
CryptoJS.RIPEMD160(str);
  • sha 系列:sha1、sha2、sha3…

sha 具有一系列散列算法

The SHA hash functions were designed by the National Security Agency (NSA). SHA-1 is the most established of the existing SHA hash functions, and it’s used in a variety of security applications and protocols. Though, SHA-1’s collision resistance has been weakening as new attacks are discovered or improved.

SHA-256 is one of the four variants in the SHA-2 set. It isn’t as widely used as SHA-1, though it appears to provide much better security.

SHA-512 is largely identical to SHA-256 but operates on 64-bit words rather than 32.
CryptoJS also supports SHA-224 and SHA-384, which are largely identical but truncated versions of SHA-256 and SHA-512 respectively.

SHA-3 is the winner of a five-year competition to select a new cryptographic hash algorithm where 64 competing designs were evaluated.
SHA-3 can be configured to output hash lengths of one of 224, 256, 384, or 512 bits. The default is 512 bits.

引入 sha 相关 js

<script src="cryptojs/rollups/sha1.js"></script>
<script src="cryptojs/rollups/sha3.js"></script>
<script src="cryptojs/rollups/sha224.js"></script>
<script src="cryptojs/rollups/sha256.js"></script>
<script src="cryptojs/rollups/sha384.js"></script>
<script src="cryptojs/rollups/sha512.js"></script>

调用 sha 相关方法

var str = '123456';
CryptoJS.SHA1(str);

var str = '123456';
CryptoJS.SHA3(str);

// 配置输出的哈希长度
CryptoJS.SHA3(str, {outputLength : 224});
CryptoJS.SHA3(str, {outputLength : 256});
CryptoJS.SHA3(str, {outputLength : 384});
CryptoJS.SHA3(str, {outputLength : 512});

var str = '123456';
CryptoJS.SHA224(str);

var str = '123456';
CryptoJS.SHA256(str);

var str = '123456';
CryptoJS.SHA284(str);

var str = '123456';
CryptoJS.SHA512(str);
  • hmac 系列:hmac_md5、hmac_ripemd160、hmac_sha1、hmac_sha3…

引入 hmac 相关 js

<script src="cryptojs/rollups/hmac-sha1.js">
</script>
<script src="cryptojs/rollups/hmac-sha3.js">
</script>
<script src="cryptojs/rollups/hmac-sha224.js">
</script>
<script src="cryptojs/rollups/hmac-sha256.js">
</script>
<script src="cryptojs/rollups/hmac-sha384.js">
</script>
<script src="cryptojs/rollups/hmac-sha512.js">
</script>

调用 hmac 相关 方法

var str = '123456';
var password = 'password';

// Hmac 相关调用前都增加了 Hmac
CryptoJS.HmacMD5(str, password);
CryptoJS.HmacRIPEMD160(str, password);
CryptoJS.HmacSHA1(str, password);
CryptoJS.HmacSHA3(str, password);
CryptoJS.HmacSHA224(str, password);
CryptoJS.HmacSHA256(str, password);
CryptoJS.HmacSHA384(str, password);
CryptoJS.HmacSHA512(str, password);

使用 Crypto-JS 进行加密、解密

Crypto-JS 相关 encrypt 函数会并不直接返回字符串,需要调用返回对象的 toString 方法,或者通过 Crypto-JS 转码才能得到真实的结果。

  • AES

引入 aes.js

<script src="cryptojs/rollups/aes.js"></script>

调用 CryptoJS.AES

// 官方示例, 每次输出的密文都不一样
CryptoJS.AES.encrypt("Message", "Secret Passphrase");

// 正确用法

var str = '123456';
// 密钥 16 位
var key = '0123456789abcdef';
// 初始向量 initial vector 16 位
var iv = '0123456789abcdef';
// key 和 iv 可以一致

key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);

var encrypted = CryptoJS.AES.encrypt(str, key, {
	iv: iv,
	mode: CryptoJS.mode.CBC,
	padding: CryptoJS.pad.Pkcs7
});

// 转换为字符串
encrypted = encrypted.toString();

// mode 支持 CBC、CFB、CTR、ECB、OFB, 默认 CBC
// padding 支持 Pkcs7、AnsiX923、Iso10126
// 、NoPadding、ZeroPadding, 默认 Pkcs7, 即 Pkcs5

var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
	iv: iv,
	mode: CryptoJS.mode.CBC,
	padding: CryptoJS.pad.Pkcs7
});

// 转换为 utf8 字符串
decrypted = CryptoJS.enc.Utf8.stringify(decrypted);

// 引入其他加密模式, 填充模式需要引入对应的 js 文件
/*
cryptojs/components/mode-cfb-min.js
cryptojs/components/mode-ctr-min.js
cryptojs/components/mode-ecb-min.js
cryptojs/components/mode-ofb-min.js
cryptojs/components/pad-ansix923-min.js
cryptojs/components/pad-iso10126-min.js
cryptojs/components/pad-iso97971-min.js
cryptojs/components/pad-nopadding-min.js
*/
  • DES、Triple DES

DES、Triple DES 的调用形式与 AES 一致。

引入 triple.js, DES 和 Triple DES 都定义在 tripledes.js

<script src="cryptojs/rollups/tripledes.js"></script>

调用 CryptoJS.DES, CryptoJS.TripleDES

var str = '123456';
var key = '0123456789abcdef';
var iv = '0123456789abcdef';

key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);

// DES 加密
var encrypted = CryptoJS.DES.encrypt(str, key, {
	iv: iv,
	mode: CryptoJS.mode.CBC,
	padding: CryptoJS.pad.Pkcs7
});

// 转换为字符串
encrypted = encrypted.toString();

// DES 解密
var decrypted = CryptoJS.DES.decrypt(encrypted, key, {
	iv: iv,
	mode: CryptoJS.mode.CBC,
	padding: CryptoJS.pad.Pkcs7
});

// 转换为 utf8 字符串
decrypted = CryptoJS.enc.Utf8.stringify(decrypted);

// Triple DES 加密
var encrypted = CryptoJS.TripleDES.encrypt(str, key, {
	iv: iv,
	mode: CryptoJS.mode.CBC,
	padding: CryptoJS.pad.Pkcs7
});

// 转换为字符串
encrypted = encrypted.toString();

// Triple DES 解密
var decrypted = CryptoJS.TripleDES.decrypt(encrypted, key, {
	iv: iv,
	mode: CryptoJS.mode.CBC,
	padding: CryptoJS.pad.Pkcs7
});

// 转换为 utf8 字符串
decrypted = CryptoJS.enc.Utf8.stringify(decrypted);
  • Rabbit、RC4

Rabbit、RC4 调用方式一致,不支持 mode、padding。

引入 rabbit.js

<script src="cryptojs/rollups/rabbit.js"></script>

调用 CryptoJS.Rabbit

var str = '123456';
var key = '0123456789abcdef';
var iv = '0123456789abcdef';

key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);

var encrypted = CryptoJS.Rabbit.encrypt(str, key, {
	iv: iv
});

// 转换为字符串
encrypted = encrypted.toString();

var decrypted = CryptoJS.Rabbit.decrypt(encrypted, key, {
	iv: iv
});

// 转换为 utf8 字符串
decrypted = CryptoJS.enc.Utf8.stringify(decrypted);

引入 rc4.js

<script src="cryptojs/rollups/rc4.js"></script>

调用 CryptoJS.RC4

var str = '123456';
var key = '0123456789abcdef';
var iv = '0123456789abcdef';

key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);

var encrypted = CryptoJS.RC4.encrypt(str, key, {
	iv: iv
});

// 转换为字符串
encrypted = encrypted.toString();

var decrypted = CryptoJS.RC4.decrypt(encrypted, key, {
	iv: iv
});

// 转换为 utf8 字符串
decrypted = CryptoJS.enc.Utf8.stringify(decrypted);

Crypto-JS 文件目录结构

  • cryptojs
    • components
      • aes.js
      • cipher-core.js
      • core.js
      • enc-base64.js
      • enc-utf16.js
      • evpkdf.js
      • format-hex.js
      • hmac.js
      • lib-typedarrays.js
      • md5.js
      • mode-cfb.js
      • mode-ctr.js
      • mode-ctr-gladman.js
      • mode-ecb.js
      • mode-ofb.js
      • pad-ansix923.js
      • pad-iso10126.js
      • pad-iso97971.js
      • pad-nopadding.js
      • pad-zeropadding.js
      • pbkdf2.js
      • rabbit.js
      • rabbit-legacy.js
      • rc4.js
      • ripemd160.js
      • sha1.js
      • sha3.js
      • sha224.js
      • sha256.js
      • sha384.js
      • sha512.js
      • tripledes.js
      • x64-core.js
    • rollups
      • aes.js
      • hmac-md5.js
      • hmac-ripemd160.js
      • hmac-sha1.js
      • hmac-sha3.js
      • hmac-sha224.js
      • hmac-sha256.js
      • hmac-sha384.js
      • hmac-sha512.js
      • md5.js
      • pbkdf2.js
      • rabbit.js
      • rabbit-legacy.js
      • rc4.js
      • ripemd160.js
      • sha1.js
      • sha3.js
      • sha224.js
      • sha256.js
      • sha384.js
      • sha512.js
      • tripledes.js

cryptojs/components 目录下的所有文件都会对应一个压缩文件,比如 cryptojs/components/aes.js 同时会有一个 cryptojs/components/aes-min.js 文件。

cryptojs/rollups 目录下的所有文件都已经压缩完毕,每个文件都可以单独调用。

phpDocumentor 使用介绍

开发 PHP 不像开发 Java 有较强的文档注释规范,通过注释可以便捷地生成接口文档。

我在寻找 PHP 接口文档工具时使用过 phpDoc,页面效果不怎么好。辗转使用了 phpDocumentor,页面效果可以接受。

phpDocumentor output

使用 phpDocumentor 步骤(仅在 Windows 系统验证通过):

首先安装 php5

下载 phpDocumentor.phar 文件

访问百度盘 http://pan.baidu.com/s/1bnErGXh 下载 phar 文件。

在 PHP5 目录(php.ini 所在的目录)下创建 phar 目录,并把 phpDocumentor.phar 移动到该目录。

进入 PHP5 目录,打开 cmd 命令窗口,执行 phpDocumentor 命令

php phar\phpDocumentor.phar -d D:\ran\framework -t D:\zhengxianjun_cdn\www\ran-api

-d 参数表示源代码目录

-t 参数表示生成的接口文档存放目录

命令执行完成之后会在 D:\zhengxianjun_cdn\www\ran-api\reports\errors.html 记录下源代码中接口描述不规范的点,逐条修改即可。

phpDocument 生成的接口文档的样式中模式会使用 Google 的字体,在国内自然打不开,导致网页打开很慢。找到 D:\zhengxianjun_cdn\www\ran-api\css\template.css,删除第一行的 @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro);。因为每次生成接口文档都会覆盖 template.css,另一个一劳永逸的办法是在 hosts 文件中加上 127.0.0.1 fonts.googleapis.com

phpDocument 生成的接口文档适配手机网页,但查看不是很便捷。

使用 phpDocument,就需要按照它的规范来抒写代码注释。

phpDocument 代码注释规范:http://www.phpdoc.org/docs/latest/index.html

支持 28 个标签,有些标签没有完全实现,但实际常用的标签就 10 个左右。

在注释文档中支持部分 html 标签,例如

phpDocument source code

对应的展示效果如下

phpDocumentor 效果

想要编写复杂的代码示例仍然不是很容易,但通过注释生成接口文档基本已满足我的需求。

想要细致了解 phpDocument.phar 文件的用法,可以通过 php phar\phpDocumentor.phar –help 命令获得帮助。

示例站点

PHP Ran Framework 的接口文档便是通过 phpDocumentor 创建的 http://ran-api.qiniudn.com

PHP 图片压缩、图片缩放

使用 PHP 进行图片压缩,首先通过 imagecreatefrom* 系列函数创建源图像 resource 对象,再通过 imagecreate 或者 imagecreatetruecolor 函数创建确定宽度和高度的目标图像对象,接着进行一系列处理,最后通过 imagecopy* 系列函数把源图像对象拷贝到目标图像对象。完成上述处理之后,调用 imagegif、imagejpeg、imagepng 把目标图像对象转换为图像字符串输出到文件或者浏览器。似乎没有直接把图像对象转换为字符串的函数?可以通过 ob_start 捕获字符串输出,并调用 ob_get_clean 取得字符串。

imagecreatefrom* 系列函数

imagecreatefromgd 从 GD 文件或 URL 创建图像对象
imagecreatefromgd2 从 GD2 文件或 URL 创建图像对象
imagecreatefromgif 从 gif 文件创建图像对象
imagecreatefromjpeg 从 jpeg/jpg 文件创建图像对象
imagecreatefrompng 从 png 文件创建图像对象
imagecreatefromwbmp 从 wbmp 文件创建图像对象
imagecreatefromwebp 从 webp 文件创建图像对象
imagecreatefromxbm 从 xbm 文件创建图像对象
imagecreatefromxpm 从 xpm 文件创建图像对象
上述所有函数全部接收一个参数 — $filename, 失败时均会返回 false
imagecreatefromstring 从字符串创建图像对象
接收一个参数 — 图像二进制字符串

imagecopy* 系列函数

imagecopy 拷贝图像的一部分
imagecopymerge 拷贝并合并图像的一部分
imagecopymergegray 用灰度拷贝并合并图像的一部分
imagecopyresampled 重采样拷贝部分图像并调整大小
imagecopyresized 拷贝部分图像并调整大小

图片压缩实现代码

$image = 'D:\TEMP\woxinfeishi-bukezhuanye.jpg';
$source = imagecreatefromjpeg($image);

$s_width = imagesx($source);
$s_height = imagesy($source);

$max_width = 200;
$max_height = 200;

if ($s_width > $max_width
	|| $s_height > $max_height)
{
	$s_rate = $s_width / $s_height;
	$t_rate = $max_width / $max_height;

	if ($s_rate > $t_rate)
	{
		$t_width = $max_width;
		$t_height = floor($t_width / $s_rate);
	}
	else
	{
		$t_height = $max_height;
		$t_width = floor($t_height * $s_rate);
	}

	$target = imagecreatetruecolor($t_width,
		$t_height);
	imagecopyresampled($target, $source, 0, 0, 0, 0,
		$t_width, $t_height,
		$s_width, $s_height);
}
else
{
	$target = $source;
}

ob_start();
imagejpeg($target);
$image_data = ob_get_clean(); // 图像数据
imagedestroy($source);
imagedestroy($target);

上述代码实现图片等比压缩,如果是缩放到固定高宽则只需要直接设置为最终高宽。

HTML特殊符号、命名实体、十进制编码对照表

HTML特殊符号、命名实体、十进制编码对照表

特殊符号 命名实体 十进制编码 特殊符号 命名实体 十进制编码
Α &Alpha; &#913; Β &Beta; &#914;
Γ &Gamma; &#915; Δ &Delta; &#916;
Ε &Epsilon; &#917; Ζ &Zeta; &#918;
Η &Eta; &#919; Θ &Theta; &#920;
Ι &Iota; &#921; Κ &Kappa; &#922;
Λ &Lambda; &#923; Μ &Mu; &#924;
Ν &Nu; &#925; Ξ &Xi; &#926;
Ο &Omicron; &#927; Π &Pi; &#928;
Ρ &Rho; &#929; Σ &Sigma; &#931;
Τ &Tau; &#932; Υ &Upsilon; &#933;
Φ &Phi; &#934; Χ &Chi; &#935;
Ψ &Psi; &#936; Ω &Omega; &#937;
α &alpha; &#945; β &beta; &#946;
γ &gamma; &#947; δ &delta; &#948;
ε &epsilon; &#949; ζ &zeta; &#950;
η &eta; &#951; θ &theta; &#952;
ι &iota; &#953; κ &kappa; &#954;
λ &lambda; &#955; μ &mu; &#956;
ν &nu; &#957; ξ &xi; &#958;
ο &omicron; &#959; π &pi; &#960;
ρ &rho; &#961; ς &sigmaf; &#962;
σ &sigma; &#963; τ &tau; &#964;
υ &upsilon; &#965; φ &phi; &#966;
χ &chi; &#967; ψ &psi; &#968;
ω &omega; &#969; ϑ &thetasym; &#977;
ϒ &upsih; &#978; ϖ &piv; &#982;
&bull; &#8226; &hellip; &#8230;
&prime; &#8242; &Prime; &#8243;
&oline; &#8254; &frasl; &#8260;
&weierp; &#8472; &image; &#8465;
&real; &#8476; &trade; &#8482;
&alefsym; &#8501; &larr; &#8592;
&uarr; &#8593; &rarr; &#8594;
&darr; &#8595; &harr; &#8596;
&crarr; &#8629; &lArr; &#8656;
&uArr; &#8657; &rArr; &#8658;
&dArr; &#8659; &hArr; &#8660;
&forall; &#8704; &part; &#8706;
&exist; &#8707; &empty; &#8709;
&nabla; &#8711; &isin; &#8712;
&notin; &#8713; &ni; &#8715;
&prod; &#8719; &sum; &#8722;
&minus; &#8722; &lowast; &#8727;
&radic; &#8730; &prop; &#8733;
&infin; &#8734; &ang; &#8736;
&and; &#8869; &or; &#8870;
&cap; &#8745; &cup; &#8746;
&int; &#8747; &there4; &#8756;
&sim; &#8764; &cong; &#8773;
&asymp; &#8773; &ne; &#8800;
&equiv; &#8801; &le; &#8804;
&ge; &#8805; &sub; &#8834;
&sup; &#8835; &nsub; &#8836;
&sube; &#8838; &supe; &#8839;
&oplus; &#8853; &otimes; &#8855;
&perp; &#8869; &sdot; &#8901;
&lceil; &#8968; &rceil; &#8969;
&lfloor; &#8970; &rfloor; &#8971;
&loz; &#9674; &spades; &#9824;
&clubs; &#9827; &hearts; &#9829;
&diams; &#9830; &nbsp; &#160;
¡ &iexcl; &#161; ¢ &cent; &#162;
£ &pound; &#163; ¤ &curren; &#164;
¥ &yen; &#165; ¦ &brvbar; &#166;
§ &sect; &#167; ¨ &uml; &#168;
© &copy; &#169; ª &ordf; &#170;
« &laquo; &#171; ¬ &not; &#172;
­ &shy; &#173; ® &reg; &#174;
¯ &macr; &#175; ° &deg; d&#176;
± &plusmn; &#177; ² &sup2; &#178;
³ &sup3; &#179; ´ &acute; &#180;
µ &micro; &#181;