【问题标题】:Determine number of leading zeros in a floating point number确定浮点数中前导零的数量
【发布时间】:2017-09-10 01:12:11
【问题描述】:

如何计算浮点数中小数点后第一个非零之前有多少个零。例子:

0 -> 0
1 -> 0
1.0 -> 0
1.1 -> 0
1.01 -> 1
1.00003456 ->4

直觉上我假设有一个数学函数可以提供这个,或者至少是主要部分。但我既不记得也不知道是哪一个。

我知道可以通过首先将数字转换为字符串来完成,只要数字不是科学计数法,但我想要一个纯数学解决方案。

在我的情况下,如果这很复杂,我不需要适用于负数的东西。

我想知道一般的方法是什么,不考虑语言。

但是如果有一个相当标准的数学函数,我也想知道 JavaScript 是否有这个函数。

顺便说一句,我想知道这个计算是否与确定整数的十进制表示需要多少位数的方法有关。

【问题讨论】:

  • 我已经更新了我的答案,刚刚意识到犯了一个小错误。

标签: javascript algorithm math floating-point language-agnostic


【解决方案1】:

x 是一个非整数,可以写成n 整数部分的数字,然后是小数点,然后m 零,然后是小数部分的其余部分。

x = [a1a2...an] . [0 102...0m][b1b2...b m]

这表示x的小数部分大于等于10-m,小于10-m+1

也就是说x的小数部分的十进制对数大于等于–m,小于–m+1

这又意味着x的小数部分的十进制对数的整个部分等于–m

function numZeroesAfterPoint(x) {
  if (x % 1 == 0) {
    return 0;
  } else {
    return -1 - Math.floor(Math.log10(x % 1));
  }
}

console.log(numZeroesAfterPoint(0));
console.log(numZeroesAfterPoint(1));
console.log(numZeroesAfterPoint(1.0));
console.log(numZeroesAfterPoint(1.1));
console.log(numZeroesAfterPoint(1.01));
console.log(numZeroesAfterPoint(1.00003456));

顺便说一句,我想知道这个计算是否与确定整数的十进制表示需要多少位数的方法有关。

以同样的方式,一个正整数xn 十进制数字来表示它当且仅当n - 1 <= log10(x) < n

所以x的十进制表示的位数是floor(log10(x)) + 1

也就是说,我不建议在实践中使用这种确定位数的方法。 log10 不能保证给出精确的对数值(甚至不如 IEEE 754 允许的那样精确),这可能会在某些极端情况下导致不正确的结果。

【讨论】:

  • 就我而言,我只处理货币和汇率。我使用的是小数点后 4 位,但是当我将 IRR 与 KWD 进行比较时,它就被打破了,所以我也对它感兴趣,因为它是一个纯数学问题(-:
  • 补充这个出色的答案:与底层二进制格式相比,基于浮点数的十进制表示的计算总是会出现问题,因为它固有的不精确性。在尝试这样做之前,我建议尝试了解浮点数的工作原理:一个好的起点是 www.exploringbinary.com。
  • 我接受这个答案是因为我能够独立提出一个 while 循环解决方案,但我真的对数学解决方案很感兴趣。
  • 由于前面提到的浮点问题,它为1.001返回3
【解决方案2】:

您可以通过一个简单的while 循环来做到这一点:

function CountZeros(Num) {

    var Dec = Num % 1;
    var Counter = -1;

    while ((Dec < 1) && (Dec > 0)) {
        Dec = Dec * 10;
        Counter++;
    }
    Counter = Math.max(0, Counter); // In case there were no numbers at all after the decimal point.

    console.log("There is: " + Counter + " zeros");
}

然后只需将要检查的数字传递给函数:

CountZeros(1.0034);

【讨论】:

  • 这个不稳定,当1.0000340001120输入时返回4
  • 仍然返回 4
  • 你希望它返回什么?
  • @turmuka 请阅读原始问题在小数点之后但在第一个非零之前有多少个零
  • 当我意识到真正的问题@MattNewelski :) 后,我也更新了我的答案
【解决方案3】:

我的方法是使用while() 循环,将.floor(n) 值与n.toFixed(x) 值进行比较,同时递增x 直到两者不相等:

console.log(getZeros(0));           //0
console.log(getZeros(1));           //0
console.log(getZeros(1.0));         //0
console.log(getZeros(1.1));         //0
console.log(getZeros(1.01));        //1
console.log(getZeros(1.00003456));  //4

function getZeros(num) {
    var x = 0;
    if(num % 1 === 0) return x;
    while(Math.floor(num)==num.toFixed(x)) {x++;}
    return(x-1);
}

【讨论】:

  • 虽然使用循环可能看起来效率低下,但对于 1.001 值它可以正常工作,这与为 1.001 返回 3 的公认答案不同
【解决方案4】:

你可以用toFixed()方法做到,但是我的代码只有一个缺陷,你需要指定点.之后的数字的长度这是因为使用方法的方式.

注意:

toFixed() 方法的最大长度是 20,所以不要在 . 后面输入超过 20 个数字,如 in the docs 所说

var num = 12.0003400;

var lengthAfterThePoint = 7;
var l = num.toFixed(lengthAfterThePoint);
var pointFound = false;
var totalZeros = 0;

for(var i = 0; i < l.length; i++){
  if(pointFound == false){
    if(l[i] == '.'){
      pointFound = true;
    }
  }else{
    if(l[i] != 0){
      break;
    }else{
      totalZeros++;
    }
  }
}
console.log(totalZeros);

额外答案

这是我的额外答案,在这个函数中,程序会计算所有的零,直到最后一个非零。所以它会忽略最后的所有零。

var num = 12.034000005608000;

var lengthAfterThePoint = 15;
var l = num.toFixed(lengthAfterThePoint);
var pointFound = false;
var theArr = [];

for(var i = 0; i < l.length; i++){
  if(pointFound == false){
    if(l[i] == '.'){
      pointFound = true;
    }
  }else{
    theArr.push(l[i]);
  }
}


var firstNumFound = false;
var totalZeros = 0;

for(var j = 0; j < theArr.length; j++){
  if(firstNumFound == false){
    if(theArr[j] != 0){
      firstNumFound = true;
      totalZeros = totalZeros + j;
    }
  }else{
    if(theArr[j] == 0){
      totalZeros++;
    }
  }
}


var totalZerosLeft = 0;
for (var k = theArr.length; k > 0; k--) {
  if(theArr[k -1] == 0){
    totalZerosLeft++;
  }else{
    break;
  }
}

console.log(totalZeros - totalZerosLeft);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多