确定浮点数中的前导零数

Determine number of leading zeros in a floating point number

提问人:hippietrail 提问时间:9/10/2017 更新时间:9/10/2017 访问量:1824

问:

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

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

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

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

就我而言,如果这是一个复杂的问题,我不需要适用于负数的东西。

我想知道一般的方法是什么,不管语言如何。

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

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

JavaScript 算法 数学 浮点 语言不可知

评论

1赞 C.Unbay 9/10/2017
我已经更新了我的答案,只是意识到犯了一个小错误。

答:

0赞 C.Unbay 9/10/2017 #1

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

注意:

方法的最大长度为 20,因此不要按照文档中所述输入超过 20 个数字toFixed().

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);
2赞 Amit Sheen 9/10/2017 #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);

评论

0赞 C.Unbay 9/10/2017
这不能稳定地工作,输入时返回 41.0000340001120
0赞 C.Unbay 9/10/2017
仍然返回 4
0赞 Amit Sheen 9/10/2017
你希望它返回什么?
1赞 mnewelski 9/10/2017
@turmuka请阅读原始问题:小数点后但在第一个非零之前有多少个零
1赞 C.Unbay 9/10/2017
一旦我意识到真正的问题,我也更新了我的答案@MattNewelski :)
5赞 Anton 9/10/2017 #3

假设是一个非整数,可以写成整个部分的数字,然后是小数点,然后是零,然后是小数部分的其余部分。xnm

x = [一个1一个2...一个n] . [0102...0][b1b2...B]

这意味着 的小数部分大于或等于 10–m,小于 10–m+1x

换言之,小数部分的十进制对数大于或等于 ,小于 。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));

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

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

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

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

评论

0赞 hippietrail 9/10/2017
就我而言,我只处理货币和汇率。我使用了 4 位小数,但当我将 IRR 与 KWD 进行比较时,这种情况就崩溃了,所以我也对它作为一个纯数学问题感兴趣(-:
1赞 Simon Byrne 9/11/2017
补充这个出色的答案:基于浮点数的十进制表示的计算总是会有问题的,因为与底层二进制格式相比,固有的不精确性。在尝试这样做之前,我建议尝试了解浮点数的工作原理:一个好的起点是 www.exploringbinary.com。
0赞 hippietrail 9/11/2017
我接受这个答案是因为我能够独立地提出一个 while 循环解决方案,但我对数学解决方案非常感兴趣。
2赞 pumbo 3/19/2020
由于上述浮点问题,它返回 3 for1.001
2赞 mnewelski 9/10/2017 #4

我的方法是使用一个循环,将值与它的值进行比较,同时递增直到两者不相等: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赞 pumbo 3/19/2020
虽然使用循环可能看起来效率低下,但它对 value 工作正确,这与返回 3 的已接受答案不同1.0011.001