【问题标题】:For Loops inside For Loops inside For Loops... = ProblemsFor 循环内的 For 循环内的 For 循环内的 For 循环... = 问题
【发布时间】:2012-07-17 23:15:58
【问题描述】:

所以。我在 JS 中的其他 for 循环中有 4 个 for 循环,并且我的代码出现(FireBug 同意我的观点)我的代码在语法上是合理的,但它拒绝工作。我正在尝试通过使用巧合索引和 Kappa 测试来计算 vigenere 密码中的密钥长度

我的主要问题是,当我尝试运行 keylengthfinder() 函数时,由于 Firefox 的内存使用量超过 1GB,CPU 超过 99%,因此该任务的计算量似乎太高,无法运行 Javascript。任何关于如何解决这个问题的想法,即使需要更长的时间来计算,也将不胜感激。这是相同代码的链接 - http://pastebin.com/uYPBuZZz - 很抱歉此代码中的任何缩进问题。我在将其正确放置在页面上时遇到问题。

function indexofcoincidence(text){
    text = text.split(" ").join("").toUpperCase();
    var textL = text.length;
    var hashtable = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
    var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (d=0; d<=25; d++) {
        for (i=0; i < textL; i++){
            if (text.charAt(i) === alphabet.charAt(d)){
            hashtable[d] = hashtable[d] + 1;
            }
        }
    }

    var aa = hashtable[0]/textL;
    var A = aa*aa;
    var bb = hashtable[1]/textL;
    var B = bb*bb;
    var cc = hashtable[2]/textL;
    var C = cc*cc;
    var dd = hashtable[3]/textL;
    var D = dd*dd;
    var ee = hashtable[4]/textL;
    var E = ee*ee;
    var ff = hashtable[5]/textL;
    var F = ff*ff;
    var gg = hashtable[6]/textL;
    var G = gg*gg;
    var hh = hashtable[7]/textL;
    var H = hh*hh;
    var ii = hashtable[8]/textL;
    var I = ii*ii;
    var jj = hashtable[9]/textL;
    var J = jj*jj;
    var kk = hashtable[10]/textL;
    var K = kk*kk;
    var ll = hashtable[11]/textL;
    var L = ll*ll;
    var mm = hashtable[12]/textL;
    var M = mm*mm;
    var nn = hashtable[13]/textL;
    var N = nn*nn;
    var oo = hashtable[14]/textL;
    var O = oo*oo;
    var pp = hashtable[15]/textL;
    var P = pp*pp;
    var qq = hashtable[16]/textL;
    var Q = qq*qq;
    var rr = hashtable[17]/textL;
    var R = rr*rr;
    var ss = hashtable[18]/textL;
    var S = ss*ss;
    var tt = hashtable[19]/textL;
    var T = tt*tt;
    var uu = hashtable[20]/textL;
    var U = uu*uu;
    var vv = hashtable[21]/textL;
    var V = vv*vv;
    var ww = hashtable[22]/textL;
    var W = ww*ww;
    var xx = hashtable[23]/textL;
    var X = xx*xx;
    var yy = hashtable[24]/textL;
    var Y = yy*yy;
    var zz = hashtable[25]/textL;
    var Z = zz*zz;

    var Kappa = A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z;
    var Top = 0.027*textL;
    var Bottom1 = 0.038*textL + 0.065;
    var Bottom2 = (textL - 1)*Kappa;
    var KeyLength = Top/(Bottom2 - Bottom1) ;

    return Kappa/0.0385;
}

function keylengthfinder(text){
    // Average Function Definition
    Array.prototype.avg = function() {
        var av = 0;
        var cnt = 0;
        var len = this.length;
        for (var i = 0; i < len; i++) {
            var e = +this[i];
            if(!e && this[i] !== 0 && this[i] !== '0') e--;
            if (this[i] == e) {av += e; cnt++;}
    }
        return av/cnt;
    }
    // Begin the Key Length Finding
    var textL = text.length;
    var hashtable = new Array(0,0,0,0,0,0,0,0,0,0,0,0);
        for (a = 0; a <= 12; a++){ // This is the main loop, testing each key length
            var stringtable = [];
            for (z = 0; z <= a; z++){ // This allows each setting, ie. 1st, 4th, 7th AND 2nd, 5th, 8th to be tested
                for (i = z; i < textL; i + a){
                    var string = '';
                    string = string.concat(text.charAt(i)); // Join each letter of the correct place in the string
                    stringtable[z] = indexofcoincidence(string);
                    }
                }
            hashtable[a] = stringtable.avg();
        }
    return hashtable;
}

【问题讨论】:

  • 如果没有适当的缩进,很难遵循代码。
  • text 的长度是多少?似乎复杂性应该或多或少O(text.length^2)。另外,请让您的代码缩进更具可读性。
  • 抱歉代码缩进。我正在努力修复它。对于那个很抱歉。文本被设计为任意长度。
  • 另外,您可能希望删除用于缓存值的变量,例如 text.length,它们不太可能会影响性能和损害可读性,而不是帮助它。
  • 性能限制为 12 * 12 * n * 25 * n,其中 25 * n 个函数调用中有 144 * n。如果字符串有 100 个字符,那就是 3600 万次迭代(大约)。对于 1000 个字符,大约是 360 亿。对?您正在测试的字符串的长度是多少?

标签: javascript cryptography vigenere


【解决方案1】:

你的问题肯定就在这里

for (i = z; i < textL; i + a){
  var string = '';
  string = string.concat(text.charAt(i)); // Join each letter of the correct place in the string
  stringtable[z] = indexofcoincidence(string);
 }

请注意,如果a=0 i 永远不会改变,因此您处于无限循环中。

【讨论】:

  • 太棒了。这似乎解决了很多问题,非常感谢!现在,该循环内部的部分给我带来了问题。我试图隔离每个第 2、3、4、5 个字母等,然后在其上运行 Indexofcoincidence() 函数。 “字符串”变量似乎仅限于一个字符。建议?再次感谢!
【解决方案2】:
Array.prototype.avg = function() {...}

应该只执行一次,而不是每次调用keylengthfinder

var Top = 0.027*textL;
var Bottom1 = 0.038*textL + 0.065;
var Bottom2 = (textL - 1)*Kappa;
var KeyLength = Top/(Bottom2 - Bottom1) ;
return Kappa/0.0385;

如果您根本不使用这些变量,为什么还要计算它们?

var string = '';
string = string.concat(text.charAt(i)); // Join each letter of the correct place in the string
stringtable[z] = indexofcoincidence(string);

我不知道你想在这里做什么。 string 永远只有一个字符?

for (i = z; i < textL; i + a) {
    ...
    stringtable[z] = ...
}

在此循环中,您正在计算从 ztextLi 的值 - 但您每次都会覆盖相同的数组项。因此,计算i=textL-1stringtable[z] 就足够了——否则你的算法有缺陷。

indexofcoincidence 函数的更短更简洁的变体:

function indexofcoincidence(text){
    var l = text.replace(/ /g, "").length;
    text = text.toUpperCase().replace(/[^A-Z]/g, "");
    var hashtable = {};
    for (var i=0; i<l; i++) {
        var c = text.charAt(i);
        hashtable[c] = (hashtable[c] || 0) + 1;
    }
    var kappa = 0;
    for (var c in hashtable)
        kappa += hashtable[c] * hashtable[c];
    return kappa/(l*l)/0.0385;
}

好的。现在我们发现了你的问题(包括a=0 的无限循环,由 qw3n 检测到),让我们重写循环:

function keylengthfinder(text) {
    var length = text.length,
        probabilities = []; // probability by key length
        maxkeylen = 13; // it might make more sense to determine this in relation to length

    for (var a = 1; a <= maxkeylen; a++) { // testing each key length
        var stringtable = Array(a); // strings to check with this gap
        // read "a" as stringtable.length
        for (var z = 0; z < a; z++) {
            var string = '';
            for (var i = z; i < textL; i += a) {
                string += text.charAt(i);
            }
            // a string consisting of z, z+a, z+2a, z+3a, ... -th letters
            stringtable[z] = string;
        }
        var sum = 0;
        // summing up the coincidence indizes for current stringtable
        for (var i=0; i<a; i++) {
            sum += indexofcoincidence(stringtable[i]);
        }
        probabilities[a] = sum / a; // average
    }
    return probabilities;
}

每个循环语句都已针对您的原始脚本进行了更改!

  • 永远不要忘记将运行变量声明为本地变量(var 关键字)
  • a 需要从零开始 - 密钥的最小长度必须为 1
  • 要从 1 运行到 n,请使用 i=1; i&lt;=n; i++
  • 要从 0 运行到 n-1,请使用 i=0; i&lt;n; i++(几乎所有循环,尤其是在从零开始的数组索引上)。
  • 除了这两个之外的其他循环在正常程序中永远不会发生。如果你有从 0 到 n 或从 1 到 n-1 的循环,你应该怀疑...
  • 更新表达式需要更新运行变量。 i++i+=1 的快捷方式@ 是i=i+1 的快捷方式。您的表达式i + a 没有分配新值(a=0 问题除外)!

【讨论】:

  • 1.感谢那。我没有意识到它在循环 2 中。因为我曾经并且现在仍然对在一行中进行大型计算持谨慎态度/对此的任何提示将不胜感激。 3.使用字符串变量,我试图不断追加say。第 2 个、第 5 个、第 8 个......在找到索引索引之前将字母放入字符串中。我应该如何解决这个问题?
  • 1.不在循环中,在最外层的函数 2 中。我的意思不是进行大型计算,而是不使用它们的结果——你可以省略整个计算。 3.如果要不断追加,则不允许每轮初始化字符串:-)但是,我仍然不明白您真正想要做什么。你能给我一个短字符串迭代的例子,比如“abcdef”吗?
  • 好的。所以我正在实现这里描述的方法 - s13.zetaboards.com/Crypto/topic/123882/1 - 我已经得到了这句话“我们平均这三个 IC 并将其称为密钥长度为三的结果”。所以。应该发生的是,我正在尝试为每组可能的密钥长度(从 1 到 12)找到 indexofcoincidence 函数。为了做到这一点,例如密钥长度为 2,我需要隔离 1,3, 5,7,9个字符,以及2,4,6,8个字符,然后找到indexofcocidence,然后将两者平均。如果这有任何意义。
  • 好的。我已经编写了一些嵌套循环来满足您的需要(为每个键长度和起始索引创建字符串,平均所有具有相同长度的字符串的重合并按长度存储)。
  • 非常感谢!看来我要胜任JS还有很长的路要走。
猜你喜欢
  • 1970-01-01
  • 2021-10-28
  • 2015-11-12
  • 1970-01-01
  • 2015-03-21
  • 2015-07-02
  • 2018-11-05
  • 2019-11-10
  • 2013-10-08
相关资源
最近更新 更多