用小数javascript划分数字

时间:2013-10-31 20:15:58

标签: javascript jquery

如何将数字(金钱)平分为x数 数字可以是一个或两个小数或没有它

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

例如

3856 / 3
1285.33
1285.33
1285.34

9 个答案:

答案 0 :(得分:6)

审核其他答案

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

@ 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中的that's how float arithmetic works

但是,我发现divide最令人不安的是它提供了一个混合类型的数组(字符串和浮点数)。并且因为输出中的数字没有四舍五入(达到正确的精度),如果您要将结果添加到纸上,则不会返回到原来的numerator输入 - 也就是说,除非你对结果进行四舍五入。

我们仍在争取平等......

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

如果你将100除以7,精度为2,那么@ 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。使用模块化划分我们知道有多少&#34;切片&#34;需要贡献q+1。最后,每个qq+1都会缩小并填充输出数组。

&#13;
&#13;
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 ]
  )
&#13;
&#13;
&#13;

您将看到我将精度设为参数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 ]

答案 1 :(得分:2)

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;
}

答案 2 :(得分:0)

听起来很简单的循环/递归。

Here you go

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)

Like so

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"]

答案 3 :(得分:0)

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

&#13;
&#13;
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);
    }
  }
}
&#13;
&#13;
&#13;

由于您说您希望最后付款最高,因此您需要修改for循环中的if语句:if(i == installments-1){// last payment}

答案 4 :(得分:0)

@ 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 ]

答案 5 :(得分:0)

请检查以下代码,

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()-将数字向下舍入到最接近的整数

答案 6 :(得分:0)

如果有人正在寻找随机分布的香草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;
}

答案 7 :(得分:0)

这是基于@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)”常量快一点,但我接受性能改进,因为我是初学者,我只是按照自己的方式做到了这一点,并想分享。

答案 8 :(得分:-1)

<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