【问题标题】:In JavaScript, is there a way to make 0.84729347293923 into an integer without using any string or regex manipulation?在 JavaScript 中,有没有办法在不使用任何字符串或正则表达式操作的情况下将 0.84729347293923 转换为整数?
【发布时间】:2020-02-08 23:59:34
【问题描述】:

给定介于 0 和 1 之间的任何数字,例如 0.84729347293923,有没有一种简单的方法可以在不使用字符串或正则表达式的情况下将其变为 84729347293923?我可以考虑使用循环,这可能并不比使用字符串差,因为它是O(n)n 是位数。但是有没有更好的方法?

function getRandom() {
  let r = Math.random();
  while (Math.floor(r) !== r) r *= 10;
  return r;
}

for (let i = 0; i < 10; i++)
  console.log(getRandom());

【问题讨论】:

  • 您提供的数字不是整数。整数是一组整数和零。你可以把它弄圆,也可以把它弄平。数学上没有其他选择,
  • 您想避免字符串操作的任何特殊原因?切掉“0”。真的很简单
  • 或者至少可以使用字符串的长度吗?
  • 如果数字总是小于 1,则将其视为百分比并乘以 100。然后将其截断或四舍五入。即使它不小于 1,也适用相同的规则。
  • @GetSet 得到 84,而不是 84729347293923。

标签: javascript


【解决方案1】:

整数 mod 1 = 0,非整数 mod 1 != 0。

while ((r*=10) % 1);

【讨论】:

  • 这让我想起了在 C 中复制字符串的最简单方法之一是while(*p++ = *q++);
  • 所以你的行甚至可以只是while ((r*=10)%1);...但它与我的方法基本相同...我想知道是否有O(1) 方法
  • 我认为这是在不使用整数中的正则表达式或字符串方法的情况下将数字的浮点部分转换为 0 和 1 之间的最佳方法,我认为没有其他最佳方法可以做到这一点在javascript中。
  • @nonopolarity 是的,我同意它与 urs 基本相同
【解决方案2】:

好的,只是想重构我的代码(我意识到这很糟糕,所以这就是我发现的正确获取您要求的值的方法)。

注意:正如问题所说“给定 0 到 1 之间的任意数字”,此解决方案仅适用于 0 到 1 之间的值:

window.onload = ()=>{

    function getLen(num){
        
        let currentNumb = num;
        let integratedArray = [];
        let realLen = 0;

        /*While the number is not an integer, we will multiply the copy of the original
         *value by ten, and when the loop detects that the number is already an integer
         *the while simply breaks, in this process we are storing each transformations
         *of the number in an array called integratedArray*/
        while(!(Number.isInteger(currentNumb))){
            currentNumb *= 10;
            integratedArray.push(currentNumb);
        }

        /*We iterate over the array and compare each value of the array with an operation
         *in which the resultant value should be exactly the same as the actual item of the
         *array, in the case that both are equal we assign the var realLen to i, and
         *in case that the values were not the same, we simply breaks the loop, if the
         *values are not the same, this indicates that we found the "trash numbers", so
         *we simply skip them.*/
        for(let i = 0; i < integratedArray.length; i++){

            if(Math.floor(integratedArray[i]) === Math.floor(num * Math.pow(10, i + 1))){
                realLen = i;
            }else{
                break;
            }

        }

        return realLen;

    }

    //Get the float value of a number between 0 and 1 as an integer.
    function getShiftedNumber(num){

        //First we need the length to get the float part of the number as an integer
        const len = getLen(num);
        /*Once we have the length of the number we simply multiply the number by
         *(10) ^ numberLength, this eliminates the comma (,), or point (.), and
         *automatically transforms the number to an integer in this case a large integer*/
        return num * (Math.pow(10, len));

    }

    console.log(getShiftedNumber(0.84729347293923));

}

所以解释如下:

因为我们想在不使用任何字符串、正则表达式或任何其他东西的情况下转换这个数字,首先我们需要获取数字的长度,如果不使用字符串转换,这有点难以做到……所以我做了为此目的使用函数 getLen。

在getLen函数中,我们有3个变量:

  • currentNumb: 这个 var 是原始值(原始数字)的副本,这个值帮助我们找到数字的长度,我们可以在不改变原始引用的情况下对这个值做一些转换号码。

我们需要将这个值乘以任何时候,以将数字转换为整数,然后将该值乘以 10 到 10。 在一段时间的帮助下(此方法使数字成为假整数)。

注意: 我看到了 “假整数”,因为当我进行测试时,我意识到在数字中添加的数字比正常数字多...(非常很奇怪),所以这个愚蠢但重要的事情使得这些“垃圾号码”的过滤器成为必要,所以我们稍后处理它们。

  • integratedArray: 这个数组存储了第一个while操作的结果的值,所以这个数组中存储的最后一个数字是一个整数,但是这个数字是“假整数”之一,所以用这个我们需要稍后迭代的数组来比较这些存储的值与原始值乘以 (10 * i + 1) 的差异,所以这里是提示:

在这种情况下,该数组的前 12 个值与 Math.floor(num * Math.pow(10, i + 1))) 的运算完全相同,但在数组的第 13 个值中这些值不一样所以...是的!我们正在寻找那些“垃圾号码”。

  • realLen:这是一个变量,我们将在其中存储数字的实际长度,将该数字的浮点部分转换为整数。

【讨论】:

  • “0 到 1 之间的任意数字”
  • @Riven 当num 给定为0.84729347293923 时,你如何获得len
  • @nonopolarity 代码已更正,答案有点难,在我的代码中进行了解释,但是...要计算长度,我们首先需要将数字转换为整数或直接计算数字在逗号或点之后,这应该是这个数字的浮点部分的长度已经转换为整数,所以这就是我如何进行计算以进行转换而没有正则表达式或字符串操作,在这种情况下我通过使用逗号帮助我(通过增加 var 将数字转换为整数之前计算数字),这是一个简单的操作。
【解决方案3】:

一些二分查找方法:

如果平均长度

它包含浮点问题。

但是,嘿,它是 O(log n),有大量浪费的边计算——我猜如果有人把它们算在内,它的事件比简单的乘法更糟糕。

我更喜欢@chiliNUT 的回答。一行印章。

function floatToIntBinarySearch(number){

   const max_safe_int_length = 16;
   const powers = [
                    1,
                    10,
                    100,
                    1000,
                    10000,
                    100000,
                    1000000,
                    10000000,
                    100000000,
                    1000000000,
                    10000000000,
                    100000000000,
                    1000000000000,
                    10000000000000,
                    100000000000000,
                    1000000000000000,
                    10000000000000000
                  ]
    let currentLength = 16
    let step = 16
    
    let _number = number * powers[currentLength]
    
    while(_number % 1 != 0 || (_number % 10 | 0) == 0){
       
       step /= 2 
       if( (_number % 10 | 0) == 0 && !(_number % 1 != 0)){
         
         currentLength =  currentLength - step;
       } else {
         
         currentLength = step + currentLength;
       }
       if(currentLength < 1 || currentLength > max_safe_int_length * 2) throw Error("length is weird: " + currentLength)
       
       _number = number * powers[currentLength]
       console.log(currentLength, _number)
       if(Number.isNaN(_number)) throw Error("isNaN: " + ((number + "").length - 2) + " maybe greater than 16?")
    }
    return number * powers[currentLength]
}
let randomPower = 10 ** (Math.random() * 10 | 0)
let test = (Math.random() * randomPower | 0) / randomPower
console.log(test)
console.log(floatToIntBinarySearch(test))

【讨论】:

    猜你喜欢
    • 2011-04-19
    • 2020-12-21
    • 1970-01-01
    • 2021-03-29
    • 2019-08-29
    • 2018-11-08
    • 2019-08-27
    • 2012-08-02
    • 1970-01-01
    相关资源
    最近更新 更多