canvas实现的圆圈时钟,你看得出现在是几点么?
-
Recent Posts
Recent Comments
- admin on circle clock
- admin on js钱额转中文大写
- Loatteoutrarp on javascript node sort
- levitra net on js钱额转中文大写
- Noitogowjag on javascript node sort
Archives
Categories
Meta
-
var sortNodes = function(nodes){
var list = [], llen = 0;
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i],
nodeUp = node,
ans = [node];
while (nodeUp = nodeUp.parentNode) {
ans.unshift(nodeUp);
}
list[llen++] = ans;
}
list.sort(function(a, b){
var alen = a.length, blen = b.length;
if (a[alen - 1] == b[blen - 1]) {
return -1;
}
var minLen = alen < blen ? alen – 1 : blen – 1;
if (a[minLen] == b[minLen]) {
return alen – blen;
}
var latestAnPos = minLen – 1;
while (a[latestAnPos] != b[latestAnPos]) {
latestAnPos–;
}
latestAnPos++;
var aup = a[latestAnPos], bup = b[latestAnPos];
while (aup = aup.nextSibling) {
if (aup === bup) {
return -1
}
}
return 1;
});
var eachList, k = 0, ret = [];
while (eachList = list[k++]) {
ret[ret.length] = eachList.pop();
}
return ret;
}
矩阵连乘积问题是对于给定n个矩阵{A1,A2,A3….,An},记An的行列分别为An_row、An_col,则有A1_col == A2_row, A2_col == A3_row…..,目的是要找出其最优运算次序(括号决定其运算次序),使得矩阵的连乘次数最少。矩阵连乘符合结合律,那么其加括号方式会影响最终的运算次序,比如给定A1A2A3A4,加括号方式共有五种:
(A1(A2(A3A4)))、(A1((A2A3)A4))、((A1A2)(A3A4))、((a1(a2a3))a4)、(((A1A2)A3)A4),对应的运算次序不同,连乘的次数也不同。
加括号对最终的连乘次数有很大影响,考虑这样的3个矩阵连乘:A1A2A3,其维度分别为10*100,100*5,5*50,如果按((A1A2)A3)加括号计算,那么最终连乘次数为10*100*5 + 10*5*50 = 7500,如果按(A1(A2A3))计算,结果为100*5*50 + 10*100*50 = 75000次。
矩阵连乘积问题适合用动态规划算法求解,其最优解具有最优子结构性质;考虑n个连乘矩阵,从第k个矩阵断开,那么其加括号方式是这样(A1A2…Ak)(Ak+1…An),从整体考虑,如果从k出断开是其最好的断开方式,连乘次数应为:断开得到的两个连乘矩阵(记为A何B),A和B各自的连乘数,再加上A*B的连乘数就是最终的连乘数;如果A,B各自的连乘数不是最优的,则k就不是从整体断开的最优位置,这是一个矛盾,故A,B自身的连乘数也应该是最优的。
矩阵连乘积问题具有子问题重叠性质。对于从n个矩阵{A1,A2,A3….,An},第一次的断开位置有n-1种可能,最优断开位置要从n-1种方式中筛选,要递归的对子问题继续进行筛选。而这些子问题可以自底向上的求解。设p[i][j]为Ai到Aj的最优连乘数,得到以下递归表达式:
m[i][j] = 0 i == j
min { p[i][j] + p[k+1][j] + Ai-1*Ak*pj i < j
以下是js写的代码:
//共13个矩阵其行列分别为:40*22,22*15,......,16*41,41*24
var matrix = [40,22,15,25,10,20,15,45,18,68,16,41,24];
function MatrixChain(m){
var len = m.length-1, p = [], splitPos = [];
//初始化p
for (var i = 0; i < len; i++) {
p[i] = [];
splitPos[i] = [];
p[i][i] = 0; //对角线全部置为零
}
for (var i = 1; i < len; i++) { //遍历所有的连乘长度
for (var j = 0, jlen = len - i; j < jlen; j++) { //遍历计算当前连乘长度为i的连乘积
for (var k = j + 1; k <= j + i ; k++) { //遍历所有的断开位置
var sum = p[j][k-1]+p[k][j+i]+m[j]*m[k]*m[j+i+1];
if(sum < p[j][j+i] || !p[j][j+i]){ //筛选最小连乘积
p[j][j+i] = sum;
splitPos[j][j+i] = k; //记录j到j+i之间的最优断开位置
};
}
}
}
//以字符窜形式输出结果
var a = 1;
var marixStr = matrix.join(",").replace(/\d+/g,function(){
return "A" + (a++).toString()
}).split(",").slice(0,len);
function getResult(l,r){ //利用splitPos数据递归输出结果
if(Math.abs(r-l)<2)
return ;
var pos = splitPos[l][r];
if (l < pos-1) {
marixStr[l] = "(" + marixStr[l];
marixStr[pos - 1] = marixStr[pos - 1] + ")";
}
if(r > pos){
marixStr[pos] = "(" + marixStr[pos];
marixStr[r] = marixStr[r] + ")";
}
getResult(l,pos-1);
getResult(pos,r);
}
getResult(0,len-1);
return marixStr.join("").replace(/(A\dA\d)/g,function(match){
return match.substring(0,2)+"*"+match.substring(2)
});
}
//调用示例
alert(MatrixChain(matrix));
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
1. If Type(x) is the same as Type(y), then
a. If Type(x) is Undefined, return true.
b. If Type(x) is Null, return true.
c. If Type(x) is Number, then
i. If x is NaN, return false.
ii. If y is NaN, return false.
iii. If x is the same Number value as y, return true.
iv. If x is +0 and y is -0, return true.
v. If x is -0 and y is +0, return true.
vi. Return false. d. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.
e. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
f. Return true if x and y refer to the same object. Otherwise, return false.
2. If x is null and y is undefined, return true.
3. If x is undefined and y is null, return true.
4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
8. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
9. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.
10. Return false.
so, [] == ![] -> [] == false -> Number([]) == false -> 0 == false, retuen true
//最多处理到万亿
function toChinesePrice(lownum){
if (isNaN(lownum))
return "";
var num = "零壹贰叁肆伍陆柒捌玖";
var wei = ["", "拾", "佰", "仟"], bigWei = ["元", "万", "亿","万"];
var wei_offet = 0, curWei = -1, curN, preZero = -2, ret = [];
//处理整数部分
var quotient = lownum, remainder, temQuo;
while (quotient > 0) {
remainder = quotient % 10;
quotient = Math.floor(quotient / 10);
curWei++;
wei_offet = curWei % 4;
if (wei_offet == 0)
ret.unshift(bigWei[Math.floor(curWei / 4)]);
if (remainder == 0) { //处理0的几种情况
var temPreZero = preZero;
preZero = curWei;
if (wei_offet == 0) //如果这个0的权值对应的是这些位:"元","万","亿","万(亿)",则不需要输出零
continue;
if (curWei != (temPreZero + 1)) //如果后面跟着的不是零,输出这个零
ret.unshift("零");
continue;
}
ret.unshift(num.substring(remainder, remainder + 1) + wei[wei_offet]);
}
if (ret[0] == "壹拾") //处理头部的“壹拾”
ret[0] = "拾";
//处理小数部分
var numStr = lownum.toString(), k = numStr.indexOf('.');
if (k > -1) {
var jiao = numStr.substring(k + 1, k + 2);
jiao && jiao != "0" && ret.push(num[parseInt(jiao)] + "角");
var fen = numStr.substring(k + 2, k + 3);
fen && fen != "0" && ret.push(num[parseInt(fen)] + "分");
}
else ret.push("整");
return ret.join('');
}
示例: toChinesePrice(2123456789111.02))
伪数组是指domcument.links、document.images返回的HTMLCollection集,querySelectetAll方法的返回staticNodeList实例等。他们拥有length属性,可以通过下标访问,但并不真正的数组,通过下标访问元素在效率上较慢,不能调用Array原生的方法,故有必要对他们转换为真正的数组。
实际上除IE8以下的浏览器,其他都支持默认的伪数组转换,可通过调用Array的原生方法触发转换,如
var array = document.links; array = Array.prototype.slice.call( array, 0); //转换 //OR var ret = []; Array.prototype.push.apply( ret, array );
在IE下则只能过遍历一次处理了,参考Sizzle里伪数组转换的源代码:
var makeArray = function( array, results ) {
array = Array.prototype.slice.call( array, 0 );
if ( results ) {
results.push.apply( results, array );
return results;
}
return array;
};
// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
// Provide a fallback method if it does not work
} catch( e ) {
makeArray = function( array, results ) {
var i = 0,
ret = results || [];
if ( toString.call(array) === "[object Array]" ) {
Array.prototype.push.apply( ret, array );
} else {
if ( typeof array.length === "number" ) {
for ( var l = array.length; i < l; i++ ) {
ret.push( array[i] );
}
} else {
for ( ; array[i]; i++ ) {
ret.push( array[i] );
}
}
}
return ret;
};
}