如何将数字的值增加到下一个10,100,1000,10,000等的倍数

gar*_*uan 43 javascript math max

你必须原谅这个问题的措辞,我确信有更好,更简洁的方式来问它,但我不知道.

假设我有一个图表,所有的y轴值都是

[0,4,5,3,2,5,6]

最大值为6.所以我希望Y-Scale标记为0到10.

给出以下值

[33,26,54,23,86,23]

最大值是86,所以我希望Y-Scale从0到90.

现在假设我有以下数值

[98,253,87, 876,263]

最大值为876,因此Y标度应为0到900

现在我已经创建了以下函数,它应该给我到目前为止所需的所有最大y-scale值.

function padMaxValue(value){
        for(var i = 1; i < 1000000000000000000; i = i * 10){
            var decimalValue = value / i;

            if(value === i){
                return i;
            }

            if(decimalValue < 1 && decimalValue > 0.09){
                return i;
            }

        }
    }
Run Code Online (Sandbox Code Playgroud)

但是,给出以下值

[99,123,82,189,45]

我的函数会将y-scale max设置为1000.但是最大应该是200.我意识到我真正需要的是一种更聪明的方法来增加价值,i而不是仅仅乘以10.我需要能够将i的值增加10,一直向上然后将它增加100,一直增加到1000.然后将其增加1000,一直增加到10000,依此类推.

我觉得应该有一些干净整洁的数学方法来做到这一点.而且我也觉得1000000000000000000我在for循环中的数字背叛了我对数学的无知.

Anyhoot,这就是问题所在.有任何想法吗?

And*_*ton 82

没有必要进入字符串的土地,如果你有一个小数值,这可能会很尴尬.

function RoundedMax(a) {
    var mx = Math.max.apply(Math, a);
    if (mx == 0) {return 0};
    var size = Math.floor(Math.log(Math.abs(mx)) / Math.LN10);
    var magnitude = Math.pow(10, size);
    var yMax = Math.ceil(mx / magnitude) * magnitude;
    return yMax;
}

function RoundedMin(a) {
    var mn = Math.min.apply(Math, a);
    if (mn == 0) {return 0};
    var size = Math.floor(Math.log(Math.abs(mn)) / Math.LN10);
    var magnitude = Math.pow(10, size);
    var yMin = Math.floor(mn / magnitude) * magnitude;
    return yMin;
}

var arr = [-9.9,-1.23,-8.2,-2.01,-4.5,0];
document.write(RoundedMax(arr) + " " + RoundedMin(arr));
Run Code Online (Sandbox Code Playgroud)

输出:0 -10.

编辑根据评论更新.现在甚至可以在IE8中使用.

  • Upvote为第一个使用对数的答案,而不是像字符串长度那样愚蠢的东西. (22认同)
  • 注意:`Math.log10()`是ECMAScript 6草案的一部分,因此它尚未被广泛支持.但是,您仍然可以通过执行`Math.log(x)/ Math.LN10`来计算基数10的对数. (8认同)
  • @Tom优点.你没有做错任何事.OP实际上指定了两种不同的行为,我没有发现.要得到6得到值10,你可以使用`var yMax = Math.ceil(mx*Math.pow(10,-size - 1))*Math.pow(10,size + 1);`. (2认同)

mea*_*gar 22

我不喜欢数学,所以这里有一个非常简单/搞笑的字符串操作解决方案:

找到最大值:

var max = Math.max.apply(Math, [98,253,87, 876,263]); // 876
Run Code Online (Sandbox Code Playgroud)

拿它的第一个角色

var c = max.toString()[0] // "8"
Run Code Online (Sandbox Code Playgroud)

将其设为整数并加1

c = (c | 0) + 1 // 9
Run Code Online (Sandbox Code Playgroud)

将其转换回字符串:

c = c.toString() // "9"
Run Code Online (Sandbox Code Playgroud)

添加N - 1个零,其中N是原始数字的长度:

c += Array(max.toString().length).join("0") // "900"
Run Code Online (Sandbox Code Playgroud)

将其转换回整数:

c = (c | 0) // 900
Run Code Online (Sandbox Code Playgroud)

完成!


说真的,用数学.

  • 我喜欢它,但是因为担心我会被嘲笑出来,所以我会选择熵算法. (3认同)
  • 对于非常大的值,字符串表示将变为"NNe + XX"格式.我建议使用`Math.floor(Math.log10(max))`来可靠地检测数字而不是`max.toString().length`.(虽然在那么大,但我们开始失去浮点精度,所以我猜周围都有问题.) (3认同)

ent*_*pic 11

我相信这会为你做到这一点:

var data = [98, 253, 87, 876, 263, -155];
var max = Math.max.apply(null, data); // 
var factor = Math.pow(10, Math.floor(Math.log(Math.abs(max)) / Math.LN10)); 
if (factor == 0) { factor = 1; }                  
var magnitude = Math.ceil(max / (factor * 1.00)) * factor; 
Run Code Online (Sandbox Code Playgroud)

基本上上面发生的是以下内容:

  1. 找到样本的最大值
  2. 获取最大值长度,然后将其提高到10的幂,即345,长度= 3,因此因子为100
  3. 确保我们不除以0
  4. 将最大数除以系数得到一个小数,然后取该数字的上限,然后将其乘以系数得到正确的0.

更新:如果要查找最小值(对于负值),只需将其翻转Math.ceilMath.floor.您还必须采用最小值的绝对值,以确保不将负字符计为字符串的一部分.

var data = [98, 253, 87, 876, 263, -155];
var min = Math.min.apply(null, data);
var factor = Math.pow(10, Math.floor(Math.log(Math.abs(max)) / Math.LN10));
if (factor == 0) { factor = 1; }
var mag = Math.floor(min / (factor * 1.00)) * factor //  mag = -200;
Run Code Online (Sandbox Code Playgroud)

更新2:正如许多人在评论中所说,我们不应该使用字符串操作.我更新了代码以使用对数代替.

  • 为什么不使用对数而不是`(max +"").length`?在数学上你会使用类似`floor(log(abs(max)))+ 1`(+符号的处理)/这也适用于小于1的值 (9认同)
  • 我也不知道这里发生了什么,但是......哟! (2认同)
  • 不要按照这个答案.每当你使用数字时,你提出的答案都涉及通过字符串表示来获得数字的数学属性,那么你做错了.在这种情况下; 日志功能存在,是此作业的正确工具. (2认同)