decimal, double, float

更新: 2022-05-07

整理版本:

Rounding

JavaScript – Decimal

 

更新: 2021-08-06

 1 / 3 * 3 = ? 

如果是 double 的话 js, c# 都是 = 1 

如果是 decimal 的话 c# = 0.999999....28 个 9 

如果是 decimal Java 的话, 直接报错, 它需要特别声明保留多少小数位和多余的要怎么 rounding 才不会报错哦. 

bd1.divide(bd2, 32, RoundingMode.UP)

BigDecimal and “java.lang.ArithmeticException: Non-terminating decimal expansion” 

 

关于: 累加遇到 null 

js 没有 build in 的 sum 通常是用 reduce 自己实现

让 array = empty 的时候, 依然返回 0 

如果遇到 nullable null 会被强转成 0 所以在累加的时候 null 当作 0 看待. 

c# linq 的 sum 和上面的结果是一样的. 

但是呢 List<int?> 返回的是 int? 虽然我不知道什么时候它会是 null 啦. 

如果是手动累加的话, 比如 int? + int? 那么其中一个的值是 null 的话结果就是 null 这个要注意哦 (c# 的场景)

 

更新: 2020-06-24

如果想找出 sql column 目前最大的 decimal point 可以做乘法然后 ceiling. x10, x100, x1000 以此类推去找

select ItemCode, RRP from Item where CEILING(RRP * 100) != RRP * 100;

 

更新 2020-06-24

c# 的 rounding 默认是有看 even 和 odd 的哦. 

有空才研究在写清楚点

https://www.cnblogs.com/yjmyzz/p/4427669.html

rounding to 0.5

https://stackoverflow.com/questions/1329426/how-do-i-round-to-the-nearest-0-5

https://stackoverflow.com/questions/6137986/javascript-roundoff-number-to-nearest-0-5

 

更新: 2020-03-15

200 - 15% = 200 x (1 - 15 / 100)   or  200 - (200 * 15 / 100)

200 + 15% = 200 x (1 + 15 / 100) or 200 + (200 * 15 / 100)

 

更新: 2019-09-08 

c# and js 要 ceil floor 2 decimal point 都没有 build in 的 solution

比如 15.667 想 ceil to 15.67 

做法是 Math.Ceilling(15.667 * 100) / 100 

先做一个乘 100 然后除 100

js 的用 big.js

new Big(15.667).round(2, RoundingMode.RoundUp)

 

 

 

refers : 

http://blog.leanote.com/post/weibo-007/mysql_float_double_decimal

https://brooch.me/2016/11/17/%E6%B5%AE%E7%82%B9%E6%95%B0%E8%AE%A1%E7%AE%97%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E7%B2%BE%E7%A1%AE/

https://frontstuff.io/how-to-handle-monetary-values-in-javascript

https://www.html.cn/archives/7340

https://github.com/sarahdayan/dinero.js

https://stackoverflow.com/questions/1165761/decimal-vs-double-which-one-should-i-use-and-when

https://stackoverflow.com/questions/803225/when-should-i-use-double-instead-of-decimal

https://www.zhihu.com/question/65960911

https://exceptionnotfound.net/decimal-vs-double-and-other-tips-about-number-types-in-net/

https://currency.js.org/

https://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-currency-string-in-javascript

https://rockyee.iteye.com/blog/891538

https://blog.csdn.net/qianlong4526888/article/details/8508012

https://www.jianshu.com/p/87627d53f77b

https://stackoverflow.com/questions/3152439/what-is-a-good-mapping-of-net-decimal-to-sql-server-decimal

 

人做计算的时候用的是 十进制, 电脑计算和存储的时候用的是二进制 

十进制转换成二进制是 ok 的, 只要没有小数点.

有小数点的时候就麻烦了, 比如 

javascript 0.1 + 0.2 === 0.3 // false 结果会是 0.3xxxxxxx 后面多了很多数字

其原因就是因为 0.1 的二进制是一个无限数字... double 用 64 位来记入数字, 肯定就丢失了后面的信息...转回十进制的时候就出现了偏差. 

要解决这个问题,通常就是不要使用十进制小数点来运算,通过升级降级 ((0.1 x 10) + (0.2 x 10) ) / 10 就可以得到准确的数字了. 

在真实的实现过程里,我们不能直接拿 0.1 x 10, 因为这个也是一个运算,依然会错。我们得用 string 然后自己把小数点移动去后面,然后再转换成数字 

c# 的 decimal 就是替我们干了这些事儿. 而 js 目前没有 decimal,只能靠库帮忙了.

 

decimal 的特点是慢, 能处理的数字小. 

double 就快, 但是不精准. (这个不精准是指,当用于十进制的运算时不精准)

那么什么时候用 decimal or double 呢? 

如果你要计算东西,而这个东西的结果是可能被"人"拿来计算的, 那么我们就应该使用 decimal 

比如:钱,积分 等等

那么 double 更多使用的场景是在游戏,图形,科学等地方。需要数字很大,运算快,但是有可以有偏差的地方。

 

js 库

https://github.com/MikeMcl/decimal.js

或者它的姐妹 big.js 和 bignumber.js 也ok 

我目前用的是 big.js 因为比较轻.

big.js 默认的 round 是四舍五入

 

舍入有很多种方式哦

我以前只知道 四舍五入...

 

Half Round Up 经典的四舍五入 

Half Round Down 五舍六入 

Half Round Up negetive 听过 netegive 的 round 吗? 哈哈 !

-7.5 to -7,-7.6 to -8 (这里的 up 方向是往 positive )

Hlaf Round Down negetive 

-7.4 to -7,-7.5 to -8 

Round Half Away From 0 (远离 0)

7.5 to 8,-7.5 to -8

Round Half Towards 0

7.5 to 7,-7.5 to -7

Round to Even

7.5 to 8(因为 8 是 even 所以四舍五入),6.5 to 6(因为 7 不是 even,所以五舍四入) 

Round to Odd

7.5 to 7(因为 8 不是 odd 所以五舍四入),6.5 to 7(因为 7 是 odd,所以四舍五入) 

 

c# 和 sql decimal 转换 

https://stackoverflow.com/questions/3152439/what-is-a-good-mapping-of-net-decimal-to-sql-server-decimal

c# 可以装 28 小数位置, 前后 dynamic 

比如 0.123.... 小数后 28 位

或者 12.123... 小数后 27 位

它很灵活的, 反观 sql server 

sql server 是 set 死的, 

比如
decimal(29,28) 对应 0.123

decimal(29,27) 对应 12.123

sql server 总数可以渠道 38, 所以要尽可能对上 c# 也只能是 decimal (38,28) 前面 10位,后面 28位

所以呢, 当我们在使用 decimal 做算法是要特别敏感一些. 

一种方式是定义好 decimal 的小数, 在 c# 先 round to 指定的小数后才使用. 这样 c# 和 sql 就统一了

二就是定义 38,28 等报错才处理. 毕竟10位不小. 很少遇到问题。重要是小数后好保留好,比如做除法经常就有除不完的 case 

如果你 sql 保留的少于 c# 那么之后就会丢失掉那些小数了。

 

中小企业项目通常的做法.

首先我们得对小数点敏感。

加减乘 int 是不会出现小数点得,除非其中一个数有小数点

除法就很有可能会产生小数点了.

加减的情况下,小数点只会变得更少,因为进位嘛

乘法就可能会有小数点变多的情况, 比如 1.22 * 1.33, 乘法其中一个是 int 就不会变多,只会变少, 变多的情况下不会无穷, 最大也只是 2个相加比如 1.22 * 1.33 最多是 4 点数

加减乘是不会无穷小数点的, 即便在乘 < 0 也不会无穷

只有除会产生无穷小数点. 

我们在做计算得时候要要想清楚每一次的场景,要 round to 几位置确保人算和电脑一样。不然就会非常混乱了. 不要想说电脑能保留多少小数就保留咯...电脑是会升级的.,所以不要依赖这个,自己决定,自己 round.

 

posted @ 2019-08-10 18:08  兴杰  阅读(604)  评论(0编辑  收藏  举报