繁体   English   中英

用小数除以数字javascript

[英]divide number with decimals javascript

我怎样才能将数字(钱)平均除以 x 数字,数字可以是一位或两位小数,也可以不带

例如1000100.2112.34
我希望能够将该数字平均分成 x 部分,但是如果它不是奇数,则额外的数字到最后一个。

例如

3856 / 3
1285.33
1285.33
1285.34

回顾其他答案

重新检查这里提供的解决方案后,我注意到它们产生了一些奇怪的结果。

@GeorgeMauler 的divideCurrencyEqually似乎适用于原始问题中提供的输入。 但是如果你稍微改变它们,它会产生一个非常奇怪的结果......

// it appears to work
divideCurrencyEvenly(10,3)
=> [ '3.33', '3.33', '3.34' ]

// wups ...
divideCurrencyEvenly(10,6)
=> [ '1.67', '1.67', '1.67', '1.67', '3.32' ]

// hmm this one works ...
divideCurrencyEvenly(18,5)
=> [ '3.60', '3.60', '3.60', '3.60', '3.60' ]

// wups ...
divideCurrencyEvenly(100,7)
=> [ '14.29', '14.29', '14.29', '14.29', '14.29', '28.55' ]

虽然@ Barmar的解决方案似乎更好地履行有点...好一点点......

// it appears to work
divide(10,3)
=> [ '3.33', '3.33', 3.34 ]

// acceptable, i guess
divide(10,6)
=> [ '1.66', '1.66', '1.66', '1.66', '1.66', 1.700000000000001 ]

// hmm, not so good, but still acceptable
divide(18,5)
=> [ '3.60', '3.60', '3.60', '3.60', 3.5999999999999996 ]

// as acceptable as the last two, i guess
divide(100,7)
=> [ '14.28', '14.28', '14.28', '14.28', '14.28', '14.28', 14.320000000000007 ]

3.5999999999999996这样的数字大多是可以原谅的,因为这就是JavaScript 中浮点运算的工作原理

但是,我发现divide最令人不安的是它给出了一个混合类型的数组(字符串和浮点数)。 而且由于输出中的数字没有四舍五入(到正确的精度),如果您将结果添加到纸上,您将无法返回原始numerator输入 - 也就是说,除非您对您的数字进行四舍五入结果。


我们仍在为平等而战……

我对上述两种解决方案也存在最后的不满。 结果并不代表尽可能接近相等的分布。

如果以 2 的精度将 100 除以 7,@Barmar 的解决方案(修复了舍入问题)将给出……

[ '14.28', '14.28', '14.28', '14.28', '14.28', '14.28', 14.32 ]

如果这些是人,而且数字代表金钱,那么1 个人不应该多付4 便士 相反, 4 个人应该多付1 分钱……

[ 14.29, 14.29, 14.29, 14.29, 14.28, 14.28, 14.28 ]

尽可能接近相等


回到第一个广场

我对解决方案不满意,所以我自己做了一个, distribute .

它有 3 个参数:精度p除数d分子n

  • 它返回一个同构数组——总是一个数字数组
  • 如果你把它们加起来,你会得到一个与你原来的分子完全相等的值

它缩放分子并找到最大的整数q ,其中q * d <= n 使用模除法,我们知道需要贡献多少“切片” q+1 最后,每个qq+1都按比例缩小并填充输出数组。

 const fill = (n, x) => Array (n) .fill (x) const concat = (xs, ys) => xs .concat (ys) const quotrem = (n, d) => [ Math .floor (n / d) , Math .floor (n % d) ] const distribute = (p, d, n) => { const e = Math .pow (10, p) const [ q, r ] = quotrem (n * e, d) return concat ( fill (r, (q + 1) / e) , fill (d - r, q / e) ) } console .log ( distribute (2, 3, 10) // [ 3.34, 3.33, 3.33 ] , distribute (2, 6, 10) // [ 1.67, 1.67, 1.67, 1.67, 1.66, 1.66 ] , distribute (2, 5, 18) // [ 3.6, 3.6, 3.6, 3.6, 3.6 ] , distribute (2, 7, 100) // [ 14.29, 14.29, 14.29, 14.29, 14.28, 14.28, 14.28 ] )

您会看到我将 precision 设置为参数p ,这意味着您可以控制出现的小数位数。 还要注意结果中任何数字之间的最大差异Δ如何是Δ <= 1/10^p

distribute (0, 7, 100)
=> [ 15, 15, 14, 14, 14, 14, 14 ] // Δ = 1

distribute (1, 7, 100)
=> [ 14.3, 14.3, 14.3, 14.3, 14.3, 14.3, 14.2 ] // Δ = 0.1

distribute (2, 7, 100)
=> [ 14.29, 14.29, 14.29, 14.29, 14.28, 14.28, 14.28 ] // Δ = 0.01

distribute (3, 7, 100)
=> [ 14.286, 14.286, 14.286, 14.286, 14.286, 14.285, 14.285 ] // Δ = 0.001

distribute (4, 7, 100)
=> [ 14.2858, 14.2857, 14.2857, 14.2857, 14.2857, 14.2857, 14.2857 ] // Δ = 0.0001

distribute可以以有意义的方式被部分地施加。 这是小人可以使用它在餐厅精确分摊账单的一种方式......

// splitTheBill will use precision of 2 which works nice for monies
const splitTheBill = (people, money) =>
  distribute (2, people, money)

// partyOfThree splits the bill between 3 people
const partyOfThree = money =>
  splitTheBill (3, money)

// how much does each person pay ?
partyOfThree (67.89)
=> [ 18.93, 18.93, 18.92 ]

这是将人们分成小组的有效方法——同时注意不要将一个人分开——这通常会导致死亡……

// p=0 will yield only whole numbers in the result
const makeTeams = (teams, people) =>
  distribute (0, teams, people)

// make 4 teams from 18 people
// how many people on each team?
makeTeams (4, 18)
=> [ 5, 5, 4, 4 ]

function divide(numerator, divisor) {
    var results = [];
    var dividend = (Math.floor(numerator/divisor*100)/100).toFixed(2); // dividend with 2 decimal places
    for (var i = 0; i < divisor-1; i++) { 
        results.push(dividend); // Put n-1 copies of dividend in results
    }
    results.push(numerator - (divisor-1)*dividend); // Add remainder to results
    return results;
}

听起来像一个非常简单的循环/递归。

给你

function divideEvenly(numerator, minPartSize) {
  if(numerator / minPartSize< 2) {
    return [numerator];
  }
  return [minPartSize].concat(divideEvenly(numerator-minPartSize, minPartSize));
}

console.log(divideEvenly(1000, 333));

要使其成为货币的两位小数,在调用此函数之前将两个数字乘以 100,然后将每个结果除以 100 并调用toFixed(2)

像这样

function divideCurrencyEvenly(numerator, divisor) {
  var minPartSize = +(numerator / divisor).toFixed(2)
  return divideEvenly(numerator*100, minPartSize*100).map(function(v) {
    return (v/100).toFixed(2);
  });
}


console.log(divideCurrencyEvenly(3856, 3));
//=>["1285.33", "1285.33", "1285.34"]

由于我们在谈论金钱,通常只要总数正确加起来,几美分的差异并不重要。 因此,如果您不介意一笔付款可能比其他付款多几美分,这里有一个非常简单的分期付款解决方案。

 function CalculateInstallments(total, installments) { // Calculate Installment Payments var pennies = total * 100; var remainder = pennies % installments; var otherPayments = (pennies - remainder) / installments; var firstPayment = otherPayments + remainder; for (var i = 0; i < installments; i++) { if (i == 0) { console.log("first payment = ", firstPayment / 100); } else { console.log("next payment = ", otherPayments / 100); } } }

既然你说你想要最后的最高付款,你会想要修改 for 循环中的 if 语句: if (i==installments-1) { //last payment }

@user633183 的distribute存在问题,但仅在分频器低于 3 时才会发生。

distribute(2, 2, 560.3)
// [ '280.15' , '280.14']

distribute(2, 1, 74.10)
// [ '74.09' ]

distribute(2, 1, 74.60)
// [ '74.59' ]

我把Guffa的答案改写成了 javascript

const distribute = (precision, divider, numerator) => {
const arr = [];
  while (divider > 0) {
    let amount = Math.round((numerator / divider) * Math.pow(10, precision)) / Math.pow(10, precision);
    arr.push(amount);
    numerator -= amount;
    divider--;
  }
  return arr.sort((a, b) => b-a);
};

这是结果

distribute(0, 7, 100)
=> [ 15, 15, 14, 14, 14, 14, 14 ]

distribute(1, 7, 100)
=> [ 14.3, 14.3, 14.3, 14.3, 14.3, 14.3, 14.2 ]

distribute(2, 7, 100)
=> [ 14.29, 14.29, 14.29, 14.29, 14.28, 14.28, 14.28 ]

distribute(3, 7, 100)
=> [ 14.286, 14.286, 14.286, 14.286, 14.286, 14.285, 14.285 ]

distribute(4, 7, 100)
=> [ 14.2858, 14.2857, 14.2857, 14.2857, 14.2857, 14.2857, 14.2857 ]

// and of course

distribute(2, 2, 560.3)
=> [ 280.15, 280.15 ]

distribute(2, 1, 74.10)
=> [ 74.1 ]

distribute(2, 1, 74.60)
=> [ 74.6 ]

请检查以下代码,

function Dividently(Amount, Quantity) {
        var m = Amount* 100,
            n = m % Quantity,
            v = Math.floor(m / Quantity) / 100,
            w = Math.floor(m / Quantity+ 1) / 100;

        for (var i = 0, out = new Array(Quantity); i < Quantity; ++i) {
            out[i] = i < n ? w : v;
        }
        return out;
    }    

 var arr = Dividently(3856, 3);    

Math.floor() - 将数字向下舍入到最接近的整数

如果有人正在寻找随机分布的 vanilla JS 解决方案,这里是我的:

function fairDivision(resolution, numerator, denominator) {
    // preserves numerator(n) integrity when dividing into denominator(d) bins
    // remainders are randomly distributed into sequential bins 
    // resolution is number of significant digits after decimal
    // (-'ve resolution for insignificant digits before decimal).
    const n = numerator * Math.pow(10, resolution);
    const remainder = n % denominator;
    const base = (n - remainder) / denominator;  
    const offset = Math.floor(Math.random()*denominator); // index of first 'round-up' bin

    let arr = []
    let low= (offset + remainder) % denominator;

    let a; let b; let c = (low < offset); //logical units
    for (let i=0; i < denominator; i++) {
        a = (i < low);
        b = (i >= offset);
        if ((a && b) || (a && c) || (b && c)) {
            arr.push(base +1)
        } else{
            arr.push(base)
        }
        arr[i] = arr[i] / Math.pow(10, resolution);
    }
    return arr;
}

这是基于@Thank_you 的结论,只是为了在平等的基础上划分没有小数的部分:

//n=how many groups, lot = total units
function makeTeams2(n,lot){
  var div = lot/n;
  var portion = Math.floor(div);
  var remains = Math.round(n*((div) % 1));
  var arr = [];
  for(var i=0; i<n; i++) arr.push(portion);
  for(var i=0; i<remains; i++) arr[i] = arr[i] + 1;
  return arr;
}

// >> makeTeams2(7,100);
// >> [15,15,14,14,14,14,14]

这比@Thank_you 的 "makeTeams(teams,people)" 常量快一点,但我接受性能改进,因为我是初学者,我只是以自己的方式做到了这一点并想分享。

<button onclick="myFunction(3856,3)">Try it</button>

function myFunction(number,divide) {
        var money = number / divide;
        money = Math.ceil(money * 100) / 100;
        alert(money);   //1285.34
    }

http://jsbin.com/ucuFuLa

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM