nstr - number → string, but looks good

10 天前
 Livid

https://nstr.vercel.app/

一个处理数字显示问题的 JS 库。

尤其是在处理有小数点的数字时会很有用。

4393 次点击
所在节点    JavaScript
32 条回复
terryso
10 天前
好东西, 看看去
MENGKE
10 天前
很有用,感谢分享
pyyalt
10 天前
好用,支持!
dssxzuxc
10 天前
确实 looks good, 源码才 113 行,实现方法很巧妙。

console.log(new Decimal('0.1').plus(new Decimal('0.2')).toString())
vs
console.log(nstr(0.1+0.2))

因为设计使然,超过 4 位(可自行设定)的 9 和 0 会被认为是噪音然后截断处理,不适用多位小数严格计算场景,其他场景都不错。
retrocode
10 天前
另外如果有严格小数计算需求, 可以考虑 bignumber.js ,精度极高无任何误差, 在我以前某无聊的变态超大数计算项目里验证过, 小数点后精度 9999 无压力
Valid
10 天前
好东西
mrlmh00
10 天前
我看样例都看不懂
显示不了 451.79 ?
451.79999999456789 = 451.8
451.78999999456789 = 451.78
451.77999999456789 = 451.78
451.76999999456789 = 451.77
hamsterbase
10 天前
不推荐这个库

推荐使用 decimal.js 实现精确的计算。
而不是计算以后猜数字


0.3 - 0.1 // 0.19999999999999998
x = new Decimal(0.3)
x.minus(0.1) // '0.2'
x // '0.3'
dssxzuxc
10 天前
@mrlmh00 #7
这个库只是用来处理 0.1+0.2=0.30000000000000004 这种问题的,让简单的浮点计算适合人类阅读
产生这种问题的浮点数都有个共同的特点:一连串的 0 或者 9 ,所以这个库就检测 0/9 连续出现的次数,超过判断条件后截断全部 0/9 最后简单处理一下进位
需要多位小数严谨计算的应该用 decimal.js, bignumber.js
这个库我觉得已经说得很清楚了,nstr ,就是数字转字符串,字符串是用来看的不是计算的,不需要严谨小数点计算的前端纯展示场景非常非常多
chesha1
10 天前
为啥不用成熟的高精度库呢,这个库的规则太简单粗暴了
dssxzuxc
10 天前
@chesha1 #10 我觉得我在 4#的例子已经很有说服力了,在你想展示几个浮点数的计算结果时,你希望写的是
new Decimal(a).plus(new Decimal(b).times(new Decimal(c))).minus(new Decimal(d))
还是
nstr(a+b*c-d)
Mint0315
10 天前
有用!
mrlmh00
10 天前
@dssxzuxc 没看懂啊 451.78999999456789 = 451.78 为什么没有进位。。
dssxzuxc
10 天前
@mrlmh00 #13 研究了一下
https://github.com/shuding/nstr/blob/main/src/index.ts#L64-L77
进位失败是因为
451.78+0.01 = 451.78999999999996
而不是期望的 451.79
需要一个更稳健的进位方法来解决这个问题
chesha1
10 天前
@dssxzuxc #11 我会在后端做好 let x = new Decimal(a).plus(new Decimal(b).times(new Decimal(c))).minus(new Decimal(d)),然后让前端 {x}
UnluckyNinja
10 天前
说计算精度需求的都跑偏了,网站里面的示例很清楚了,就是为了解决数字格式化的问题,避免因为精度误差导致显示的数字过长或过早使用科学计数法.

不过 100 多行还是有点多了,网站的对比看下来,toFixed 其实很符合要求,只是不会移除尾部 0 ,那么其实再替换下尾部 0 就够了,一行解决
200.0003.toFixed(3).replace(/(\.?|(?<=\.\d+))0+$/,'')
(?<=\.\d+) 就是确保处于小数部分,避免移除了整数部分的尾部 0 ,可能还有其它边界情况没考虑,差不多这个意思。
Chuckle
10 天前
适合数据可视化上数字展示
zbinlin
9 天前
@dssxzuxc #14 我去提了个 PR
dssxzuxc
9 天前
@UnluckyNinja #16
我以前项目也写过类似的东西
```ts
function n_str(
value: number,
options: { fractionDigits?: number } = {},
): string {
const { fractionDigits = 3 } = options
const str = value.toFixed(fractionDigits).replace(/(\.?|(?<=\.\d+))0+$/, '')
return str === '-0' ? '0' : str
}
```
toFixed()的问题是无法智能判断精度,需要传入参数指定精度
nstr(1.123456) -> 1.123456
n_str(1.123456) -> 1.123
n_str(1.123456, { fractionDigits: 6 }) -> 1.123456
这里的难点是无法简单判断出浮点数计算的小数位数,比如 0.1+0.2 ,人类都知道应该是 1 位小数点,但是如何从 0.30000000000000004 解析出来,还有科学计数法把这个问题搞得更加复杂,而 nstr 能解决这个问题。手动指定精度 2 行就解决了,为了少写这个参数我不介意在项目里多 install 一个包。

目前 nstr 我测了所有情况,就剩 456.78999999456789=456.78 这个问题,其他的都正常
在 nstr 的方案上使用 toFixed 或许能解决这个问题同时不引入其他边缘情况,例如楼上的 pr
https://github.com/shuding/nstr/pull/2/commits/4713d6447bc8fd3af2e246e63ea2f0edb8445d07
bli22ard
9 天前
这个库设计很有问题,0.1+0.2 已经为浮点数了,然后又转字符串,还能将 0.1+0.2 还原为 0.3 。如果你想表示 0.33999999999999998 ,它会给你转 0.34 ,结果就是 0.33999999999999998==0.34 这么做,明显有问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1154410

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX