Javascript 什么';要求受访者手动将字符串解析为int的由来是什么?

Javascript 什么';要求受访者手动将字符串解析为int的由来是什么?,javascript,string,integer,type-conversion,Javascript,String,Integer,Type Conversion,我想知道,要求受访者手动将字符串解析为int的由来是什么?(不依赖于语言中内置的任何强制转换/类型转换)。这是一个标准的问题,是从一本书或一个列表中提出的吗 有没有其他人在面试中被问到这个问题?我想当我解释它并在白板上写下它时,我把它钉住了,因为我已经收到了一份暂定的工作邀请:) 下面是我在Javascript中的具体实现。下面有一些简单的方面(例如,它不接受基数参数),但它展示了(或多或少)正确的算法 function to_i(strValue) { //named so as to not

我想知道,要求受访者手动将字符串解析为int的由来是什么?(不依赖于语言中内置的任何强制转换/类型转换)。这是一个标准的问题,是从一本书或一个列表中提出的吗

有没有其他人在面试中被问到这个问题?我想当我解释它并在白板上写下它时,我把它钉住了,因为我已经收到了一份暂定的工作邀请:)

下面是我在Javascript中的具体实现。下面有一些简单的方面(例如,它不接受基数参数),但它展示了(或多或少)正确的算法

function to_i(strValue) { //named so as to not be confused with parseInt
    if (typeof strValue !== 'string' || strValue.length === 0) {
        return Number.NaN;
    }

    var tmpStr = strValue;
    var intValue = 0;
    var mult = 1;

    for (var pos=tmpStr.length-1; pos>=0; pos--) {
        var charCode = tmpStr.charCodeAt(pos);
        if (charCode < 48 || charCode > 57) {
            return Number.NaN;
        }

        intValue += mult * Math.abs(48-charCode);
        tmpStr = tmpStr.substr(0, tmpStr.length-1); 
        mult *= 10;
    }

    return intValue;
}
函数,以避免与parseInt混淆
if(strValue的类型!='string'| | strValue.length==0){
返回编号.NaN;
}
var tmpStr=标准值;
var intValue=0;
var-mult=1;
对于(变量pos=tmpStr.length-1;pos>=0;pos--){
var charCode=tmpStr.charCodeAt(位置);
如果(字符码<48 | |字符码>57){
返回编号.NaN;
}
intValue+=mult*Math.abs(48字符码);
tmpStr=tmpStr.substr(0,tmpStr.length-1);
mult*=10;
}
返回值;
}

也从未听说过这个问题,在美国接受采访时,他们总是问我更难的问题。我希望他们问我这么简单的问题。

我也没有被问过这个问题

乍一看,这似乎是一个“尽早剔除那些明显不称职的白痴,以避免浪费宝贵的面试时间”类型的问题

但是如果你更仔细地看,里面实际上有一些非常有趣的东西。所以,如果我是那个问这个问题的人,我想问的是:

  • 这个问题显然很愚蠢,因为ECMAScript标准库中已经有一个函数可以做到这一点。我想让被采访者告诉我这个问题很愚蠢,因为否则他们要么是a)愚蠢地遵循脑死亡指令而不是参与大脑的无脑僵尸,要么b)他们实际上不知道这个功能的存在
  • 这显然也是一个解析问题,很有意思的是,看看受访者是将其视为一个字符串黑客问题还是一个正式的解析问题,以及这两种方法会产生多少开销。在这个特殊的例子中,我相信字符串黑客是正确的方法,但它仍然导致了一个巨大的后续问题:“现在对递归下降解析器做同样的事情”。任何程序员都应该能够在几分钟内为这个问题绘制出递归下降解析器
  • 最后但并非最不重要的一点是,这显然是对字符串字符的折叠。现在,我不一定期望一个新手程序员能够立即发现这个折叠,但是如果我暗示其中存在折叠,他们应该能够自己发现它,并以折叠的形式重写他们的解决方案
  • 当然,你可以判断这类问题所允许的所有一般性质:受访者是停下来思考问题,还是开始窃听。他是否从需求、文档、规范、示例、测试或代码开始。他是否要求澄清一些特殊情况(比如空字符串会发生什么,只包含负号而不包含其他内容的字符串会发生什么,空白会发生什么,字符串是否保证是格式正确的整数,负零是否是格式正确的整数)。他是否习惯使用ES5的严格子集。他写的代码可读吗。他写的是友好的代码吗
下面是一个使用折叠解决问题的示例(在ECMAScript中称为
reduce
):

这是一个简单的递归下降解析器,可以动态地建立值:

"use strict";

function toInteger(s) {
    var input,
        output = 0,
        sign = 1,

        lookahead = function () {
            return input.charAt(0);
        },

        consume = function () {
            var res = input.slice(0, 1);
            input = input.slice(1, input.length);
            return res;
        },

        isDigit = function (c) {
            return /[0-9]/.test(c);
        },

        signParser = function () {
            if (lookahead() === '-') {
                sign *= -1;
                consume();
            }
        },

        digitParser = function () {
            if (!isDigit(lookahead())) return false;
            output *= 10;
            output += (consume().charCodeAt(0) - 48);
            return true;
        },

        numberParser = function () {
            signParser();
            while (digitParser());
        };

    input = s;
    numberParser();
    if (!input.length === 0) return false;
    output *= sign;

    return output;
}
与此类面试问题的情况一样,没有人会认真期望被面试者将这些功能写在白板上。特别是递归下降解析器。但依我看,任何人都应该能够勾勒出函数的样子。特别是,递归下降解析器的优点之一是,它将上下文无关语法非常直接地转换为一组解析函数,受访者应该能够大致解释该转换是如何工作的,以及什么样的解析函数对应什么样的语法构造



唷,这么简单的问题,你能得到很多东西

他们想测试你的数学知识,因为许多“代码猴子”没有接受适当的数学教育

以数字$d_1 d_2…d_n$表示的数字可以用以下形式书写:$d_1 r^(n-1)+…+d_(n-1)r^1+d_n$,其中r是基数

也就是说,十进制的123=1*10^2+2*10^1+3$ 八进制中的123是$1*8^2+2*8^1+3$=83

function to_i(str, rad) {
  // the function to transform an ascii code into a number value
  function dig(c) {
    if (c >= 48 && c <= 57) {
      // 0 - 9: as-is
      return c - 48;
    } else if (c >= 97 && c <= 122) {
      // a - z: a means 10, b means 11 and so on until z
      return 10 + c - 97;
    } else {
      return Number.NaN;
    }
  }

  // validate arguments
  if (str == '' || rad < 2 || rad > 35) return Number.NaN;
  // strip extra characters and lowercase ("$10" -> "10")
  var result = str.toLowerCase().match(/^.*?(-?)([a-z0-9]+).*?$/);
  // break on empty numbers
  if (result == null || !result[2]) return Number.NaN;
  // get sign multiplier
  var sign = (result[1] == '-' ? -1 : 1), val = result[2], num = 0;
  // num = dv_0 * rad ** n + dv1 * rad ** (n - 1) + ... dv_n * rad ** 0
  //  where dv_n = dig(val.charCodeAt(i))
  //  and a ** b = a * ... * a, b times
  // for each digits
  for (var i = val.length - 1, m = 1; i >= 0; i --, m *= rad) {
    // get digit value
    var dv = dig(val.charCodeAt(i));
    // validate digit value (you can't put 5 in binary)
    if (dv >= rad || num == Number.NaN) return Number.NaN;
    // multiply
    num += m * dv;
  }
  // return 
  return num * sign;
}

to_i("ff", 16);
函数到_i(str,rad){
//将ascii码转换为数值的函数
功能(c){
如果(c>=48&&c=97&&c 35)返回Number.NaN;
//带额外字符和小写($10“->“10”)
var result=str.toLowerCase().match(/^.*?((?)([a-z0-9]+).*?$/);
//打破空号
if(result==null | |!result[2])返回Number.NaN;
//获取符号乘法器
变量符号=(结果[1]='-'?-1:1),val=结果[2],num=0;
//num=dv_0*rad**n+dv1*rad**(n-1)+…dv_n*rad**0
//式中,dv_n=dig(val.charCodeAt(i))
//a**b=a*..*a,b次
//每位数
对于(变量i=val.length-1,m=1;i>=0;i--,m*=rad){
//获取数字值
var dv=dig(val.charCodeAt(i));
//验证数字值(不能将5放入二进制)
function to_i(str, rad) {
  // the function to transform an ascii code into a number value
  function dig(c) {
    if (c >= 48 && c <= 57) {
      // 0 - 9: as-is
      return c - 48;
    } else if (c >= 97 && c <= 122) {
      // a - z: a means 10, b means 11 and so on until z
      return 10 + c - 97;
    } else {
      return Number.NaN;
    }
  }

  // validate arguments
  if (str == '' || rad < 2 || rad > 35) return Number.NaN;
  // strip extra characters and lowercase ("$10" -> "10")
  var result = str.toLowerCase().match(/^.*?(-?)([a-z0-9]+).*?$/);
  // break on empty numbers
  if (result == null || !result[2]) return Number.NaN;
  // get sign multiplier
  var sign = (result[1] == '-' ? -1 : 1), val = result[2], num = 0;
  // num = dv_0 * rad ** n + dv1 * rad ** (n - 1) + ... dv_n * rad ** 0
  //  where dv_n = dig(val.charCodeAt(i))
  //  and a ** b = a * ... * a, b times
  // for each digits
  for (var i = val.length - 1, m = 1; i >= 0; i --, m *= rad) {
    // get digit value
    var dv = dig(val.charCodeAt(i));
    // validate digit value (you can't put 5 in binary)
    if (dv >= rad || num == Number.NaN) return Number.NaN;
    // multiply
    num += m * dv;
  }
  // return 
  return num * sign;
}

to_i("ff", 16);