RGJ
(Richard - Communiteq)
1
- Discourse-Subscriptionsを使用しています
- 製品に価格プランを追加しようとしています
- 価格ボックスに19.99と入力します(入力の動作が非常に奇妙なため、これはすでに困難です)
- 送信を試みます
- エラー「無効な整数 1998.9999999999998」を受け取ります
これまでのところ、stable 3.5.3でのみテストしましたが、betaでもコードは同じです。
Code
@computed("unit_amount")
get amountDollars() {
return parseFloat(this.get("unit_amount") / 100).toFixed(2);
}
set amountDollars(value) {
const decimal = parseFloat(value) * 100;
this.set("unit_amount", decimal);
}
Javascript / IEEE-754 floatの厄介な点:
-> parseFloat("19.99")*100
<- 1998.9999999999998
提案された修正: const decimal = Math.round(Number(value) * 100)
最大の疑問: なぜ誰も気づかなかったのか?誰も価格を19.99ドルに設定したことがなかったのでしょうか?
「いいね!」 2
pfaffman
(Jay Pfaffman)
2
すぐにわかりました。40年以上前に学んだコンピューターに関する、変わらないことの一つです。
あるいは1セント単位の整数を使うか?Stripeは実際そうしていると思います。(しかし、あなたの解決策は変更するコードがはるかに少ないので、そちらが優勢でしょう。)
「いいね!」 2
RGJ
(Richard - Communiteq)
3
はい、その通りです。unit_amount はセント単位で、amountDollars は「XX.XX」形式の入力値です。
「無効な整数」エラーはStripe APIから直接発生します。
FDIVバグについて知っているくらい、私たち二人とも年季が入っているようですね 
「いいね!」 3
sam
(Sam Saffron)
4
正直なところ、これを float で保存するのは誤りだと思います。この列は int で、セント単位で保存されるべきです。
「いいね!」 3
RGJ
(Richard - Communiteq)
5
parseFloat は、入力フィールド(「小数点以下2桁の通貨」)との間で変換するために使用されています。unit_amount オブジェクトのプロパティは明らかに型がないため、Math.round() の使用を提案しました。
これはサーバー側のカラムではなく、Stripe API に渡されます。
「いいね!」 1
通貨BCDでは、バイナリ浮動小数点よりもBCD浮動小数点の方が一般的に優れています。