JavaScript 中的校验和计算
在默认情况下数字是双浮点数的语言中进行整数按位数学可能非常困难。您的代码必须确保数字保持整数,甚至可能保持无符号并在特定位范围内(16 位、32 位)。这些额外的步骤可能会使事情复杂化。
技巧
确保数字是 x 位整数的一些技巧是使用 AND 运算符和允许该范围内所有位的位掩码。例如确保 16 位数字可以通过数字 &= 0xffff; 来完成。此外,我使用诸如 num | 之类的操作。 0 或 num >>> 0 以确保它是 32 位整数,有符号或无符号。这是防止产生负面结果所必需的,当您以十六进制显示校验和时,这看起来特别奇怪。
速度
显然我没有尝试这个来制作一个快速校验和引擎,我只是想在我的 SmallPRNG 和 ISAAC CPRNG 笔之后测试更多的按位计算的可能性(待定;))。这些算法在所有浏览器和浏览器版本中的执行方式都不同,在某些浏览器中甚至可能非常慢。我相信 Chrome 会非常快速地处理数据,并且可以以合理的速度计算校验和!
基类
我将实现多个校验和算法,因此我将创建一个基类,它将为所选算法构造一个状态 (ctx)。此状态将跟踪校验和和算法类的实例。这个类也会正确处理字符串,考虑到它们的编码。
该类还包含对 Uint8Array 支持的测试。我不确定这是否是测试支持的最佳方法,但它确实成功了。
var hasTyped = (function() {
if(!('Uint8Array' in window)) {
return false;
}
try {
var a = new window.Uint8Array(10);
a[0] = 100;
if(a[0] === 100) {
return true;
}
return false;
} catch (e) {
return false;
}
}());
算法类
现在我们可以使用 Checksum.registerChecksum 添加算法。每个 Algorithm 类都应该实现一个用于处理数据的单个和一个数组方法,以及一个可选的 setup 方法,该方法将在构造 Checksum 对象时调用。
BSD16
这是一个非常简单的,这个算法只需要一点代码。 BSD校验和算法!
(function() {
'use strict';
if(typeof(window.Checksum) === "undefined") {
throw "The Checksum class is required for this code.";
}
/**
* Initialize anything you want in the constructor, such as setting up a lookup
* table of bytes. Make sure to cache your calculations, so they only have to be
* done once.
*/
var BSD16 = function BSD16() {
this.init = 0;
};
/**
* bsd16 for arrays, each value must be numeric and will be bound to 8-bits (Int8Array or Uint8Array works best!)
* @param {Array} a input (8-bit array)
* @param {Number} p previous checksum state
* @returns {Number} new checksum state
*/
BSD16.prototype.array = function(a, p) {
var c = p || 0, i = 0, l = a.length;
for(; i < l; i++) c = (((((c >>> 1) + ((c & 1) << 15)) | 0) + (a[i] & 0xff)) & 0xffff) | 0;
return c;
};
/**
* bsd16 for a single value, update a checksum with a new byte
* @param {Number} b byte (0-255)
* @param {Number} p previous checksum state
* @returns {Number} new checksum state
*/
BSD16.prototype.single = function(b, p) {
var c = p || 0;
return (((((c >>> 1) + ((c & 1) << 15)) | 0) + (b & 0xff)) & 0xffff) | 0;
};
Checksum.registerChecksum("bsd16", BSD16);
}());
FNV32(FNV-0 和 FNV-1)
另一个简单的算法,FNV 哈希算法 - 生成 32 位校验和!
(function() {
'use strict';
if(typeof(window.Checksum) === "undefined") {
throw "The Checksum class is required for this code.";
}
var prime = 0x01000193;
/**
* Initialize anything you want in the constructor, such as setting up a lookup
* table of bytes. Make sure to cache your calculations, so they only have to be
* done once.
*/
var FNV32 = function FNV32() {
this.init = 2166136261; // fnv-1!
};
/**
* The setup method which will be called when new Checksum("fletcher", ...) is called.
* This method is supposed to initialize the checksum cipher and to recieve parameters
* from the constructor.
*
* @param {Number} mode the FNV32 mode (FNV-1 (defualt) or FNV-0)
*/
FNV32.prototype.setup = function(mode) {
if(mode === 0) {
this.init = 0; // fnv-0.
}
};
FNV32.prototype.array = function(a, p) {
var len = a.length,
fnv = p || this.init;
for(var i = 0; i < len; i++) {
fnv = (fnv + (((fnv << 1) + (fnv << 4) + (fnv << 7) + (fnv << 8) + (fnv << 24)) >>> 0)) ^ (a[i] & 0xff);
}
return fnv >>> 0;
};
FNV32.prototype.single = function(b, p) {
var fnv = p || this.init;
return ((fnv + (((fnv << 1) + (fnv << 4) + (fnv << 7) + (fnv << 8) + (fnv << 24)) >>> 0)) ^ (b & 0xff)) >>> 0;
};
Checksum.registerChecksum("fnv32", FNV32);
}());
您可以使用此网址阅读全文
https://codepen.io/ImagineProgramming/post/checksum-algorithms-in-javascript-checksum-js-engine?cf_chl_jschl_tk=39bd0de9934c580b6ce33374feddb9c37ee59c20-1590266531-0-AcdpYddIKyEBHAf0tuLzYDLpqpVAYrXmTKfWqF_3OLQVepxEcJq9z0gjYtxrVssDX487qBCful5gnyyFlqtl1fUzzH-lQXJhSZkUquU7GWLTAWAMbH2st22M1Ef6NxBfdHZKL5K0oLWb7gU88-MWOVWW3Ioponmmm7GVfHqSL7bdGcrSZIWjw_U2hKl57DXPw8YO3eWcykQnewEQPVOV7mQV5MlHPf17K-_Doo9NOoOtFJUQGHZyLJL2ANJAiWP98nK6vBZcIyLh69YUbuYFFgYB7uRmzfnb-NKCFLDbRUTBaq0I6Xr_blRfzAsyen4Jc-7bWN0cvNlKPQzViAxIR68edJx4gYcFIOrJiu-kQmmMQJMcHuwZFuvWCqAYLQEPX63ttncdhJUEXU8ThjhPhiHNPwX4FjzI1PxLRMH8Hoj1GlIur1DyZDxwz-4t64Pwqg