【问题标题】:JavaScript numbers not adding correctly every time parseFloat toFixed每次 parseFloat toFixed 时 JavaScript 数字都没有正确添加
【发布时间】:2019-01-17 00:18:16
【问题描述】:

我正在根据以下各项计算小计、税收、运费和保险:

public getSubTotal() {
  this.subTotal =
    document.getElementById("total").value -
    (document.getElementById("total").value * 0.07 +
      document.getElementById("total").value * 0.03 +
      document.getElementById("total").value * 0.01 +
      1.0);
  document.getElementById("tax").value =
    document.getElementById("total").value * 0.07;
  document.getElementById("shipping").value =
    document.getElementById("total").value * 0.03;
  document.getElementById("insurance").value =
    document.getElementById("total").value * 0.01;
  console.log(
    "tax: " +
      document.getElementById("total").value * 0.07 +
      " shipping: " +
      document.getElementById("total").value * 0.03 +
      " ins: " +
      document.getElementById("total").value * 0.01 +
      " total: " +
      document.getElementById("total").value +
      " subtotal: " +
      this.subTotal
  );
  return this.subTotal.toFixed(2);
}

details: {
  subtotal: document.getElementById("subTotal").value,
  tax: parseFloat(document.getElementById("tax").value).toFixed(
    2
  ),
  shipping: parseFloat(
    document.getElementById("shipping").value
  ).toFixed(2),
  handling_fee: "1.00",
  shipping_discount: "0.00",
  insurance: parseFloat(
    document.getElementById("insurance").value
  ).toFixed(2)
}

每个产品的总数是固定的。

当我将其发布到 PayPal API 时,数字有时会相加,有时却不会。我不知道如何解决它。

以下是发布内容的示例,我不明白为什么 PayPal 拒绝此示例:

details {…}
handling_fee    1.00
insurance   0.23
shipping    0.68
shipping_discount   0.00
subtotal    19.30
tax 1.60
total   22.81

所有这些数字均基于 22.81,控制台显示:

tax: 1.5967 
shipping: 0.6842999999999999 
ins: 0.2281 
total: 22.81 
subtotal: 19.3009

如何防止 parseFloat().toFixed(2) 更改数字?如果我留下的数字有两个以上的小数位数,那么 PayPal 会因为格式错误而拒绝它。

当我对这些数字使用计算器时,我得到的结果是 22.81

以下是我从 PayPal 收到的错误信息 - 如果我注释掉详细信息部分,则帖子会顺利通过:

Error: Request to post https://www.sandbox.paypal.com/v1/payments/payment failed with 400 error. Correlation id: 12d500c6247f1, 12d500c6247f1

{
    "name": "VALIDATION_ERROR",
    "details": [
        {
            "field": "transactions[0]",
            "issue": "Item amount must add up to specified amount subtotal (or total if amount details not specified)"
        }
    ],
    "message": "Invalid request - see details",
    "information_link": "https://developer.paypal.com/docs/api/payments/#errors",
    "debug_id": "12d500c6247f1"
}

以下是几个屏幕截图:

当然,随着产品数量的增加,添加的产品数量以及给定总量的差异也会增加,这导致了我的整体问题。

我应该如何正确计算这些项目?

提前致谢

【问题讨论】:

  • .toFixed() 函数返回一个字符串,而不是一个数字。添加字符串意味着字符串连接,而不是数字加法。您不能将 JavaScript 数字限制为固定的小数位数,因为 JavaScript 数字是 二进制 浮点值。
  • @Pointy 感谢您的回复。这就是我使用 parseFloat().toFixed(2) 的原因
  • 对,但是在调用.toFixed() 之后,如果您再次将其设为数字​​,您将直接返回二进制浮点数。 JavaScript(或任何其他使用二进制浮点的语言)中的“货币数学”不能可靠地工作,因为许多小数不能精确表示。
  • @Pointy 很好,那么我应该怎么做才能正确计算只有两个小数点的数字
  • 将输入乘以 100,然后进行算术运算。当你想显示结果时,除以 100 并使用toFixed(2)

标签: javascript paypal parsefloat tofixed


【解决方案1】:

当您使用货币值时,您可以通过以美分计算来避免许多舍入错误,将所有成本都以美分表示,当您显示它们时,您可以显示

(cost/100).toFixed(2)

这将在浮点上使用整数数学,并且您将获得更少的舍入误差。

【讨论】:

    【解决方案2】:

    在反复计算产品价格,然后减去税金、运费、装卸费和保险金额以达到小计之后 - 我突然意识到我正在做这个背景,并且因为浮点数有点“不可预测”,那么金额永远不会 100% 匹配。

    那是它击中我的时候,它是如此明显。我应该将所有这些数字添加到产品的价格中:

     getFinalAmount() {
      this.model.subTotal = this.subTotal = this.prdSrvc.getPriceTotal();
      this.subTotal = parseFloat(this.subTotal).toFixed(2);
    
      document.getElementById("tax").value = this.model.tax = this.tax =
        this.subTotal * 0.07;
      document.getElementById(
        "shipping"
      ).value = this.model.shipping = this.shipping = this.subTotal * 0.03;
      document.getElementById(
        "insurance"
      ).value = this.model.insurance = this.insurance = this.subTotal * 0.01;
    
      this.total = this.payPalSrvc.finalAmount =
        parseFloat(this.tax) +
        parseFloat(this.shipping) +
        parseFloat(this.insurance) +
        parseFloat(this.subTotal) +
        1.0;
    
      this.payPalSrvc.finalAmount = parseFloat(
        this.payPalSrvc.finalAmount
      ).toFixed(2);
      this.total = parseFloat(this.total).toFixed(2);
    
      document.getElementById(
        "subTotal"
      ).value = this.model.subTotal = this.subTotal;
      document.getElementById("total").value = this.model.total = this.total;
    
      this.tax = parseFloat(this.tax).toFixed(2);
      this.shipping = parseFloat(this.shipping).toFixed(2);
      this.insurance = parseFloat(this.insurance).toFixed(2);
      return this.payPalSrvc.finalAmount;
    }
    

    我还从 html 中删除了货币管道,留下了带两位小数的直数:

        <input type="hidden" name="tax" id="tax" value="{{ this.tax }}" />
        <input
          type="hidden"
          name="shipping"
          id="shipping"
          value="{{ this.shipping }}"
        />
        <input
          type="hidden"
          name="insurance"
          id="insurance"
          value="{{ this.insurance }}"
        />
    

    以下是 paypal 仪表板中订单的外观:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多