nstr - number → string, but looks good

8 天前
 Livid

https://nstr.vercel.app/

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

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

4315 次点击
所在节点    JavaScript
32 条回复
dssxzuxc
5 天前
@bli22ard #20
0.3399999999999999 = 0.34 是预期行为,这个库就是用来做这件事的。
这已经是第四遍回答了,当你需要显示/计算标准浮点/decimal 时,请使用原生 js 或者 decimal.js, bignumber.js 。
#16 已经说的很清楚了,这个库的作用是
`解决数字格式化的问题,避免因为精度误差导致显示的数字过长或过早使用科学计数法`。
设计上超过一定数量的连续 0 or 9 会直接截断,很显然这样才能实现 0.1 + 0.2 = 0.3 ,而带来的代价就是无法表达含有超过一定数量的连续 0 or 9 。
这个库的适用场景应该是大屏、统计页面等等各种数据可视化,四位以内小数运算是正确的,连续 0 or 9 超过一定次数就会自动四舍五入,严格计算老实去用 decimal.js, bignumber.js ,这只是解决了非严格 decimal 数据的展示问题,让编写显示浮点计算结果的代码更简单易懂适合人类阅读。
bli22ard
5 天前
@dssxzuxc #21 可能做法简洁,但是,我不认为是一个好方法,这样会让行为变得模糊起来。小数最佳实战应该是 decimal.js, bignumber.js 等计算完,然后格式化输出,而不是用这个格式化,造成 0.33999999999999998 看起来像 0.34 的不精确问题
UnluckyNinja
5 天前
@bli22ard #22 怎么还没绕过这个弯,就不是精度的问题。会取近似值的,epsilon 都远远大于精度误差,根本没必要上高精度库,高精度库也解决不了显示问题。
就假设我有一个原始就是 0.3000004 的数(不是通过计算得来的,可能是网络,可能是可视化的数据集,总之这个数字本身就是这个形式),不需要计算,直接显示成人类可读字符串表示,这个情况你用高精度库有什么意义吗
bli22ard
5 天前
@UnluckyNinja #23 你的 0.3000004 ,不是计算得来,那是怎么得来的?是输入吗,为什么输入的不是 0.3 ,而输入 0.3000004 ?如果输入的是 0.3000004 ,显示成 0.3 是不是有问题?你的假设是不是有问题?
635925926
5 天前
@dssxzuxc #11 那也得正确啊,不能为了写起来简单,就忽略正确性
lvlongxiang199
5 天前
太投机取巧了, 输入一个大点的 int64 就精度丢失了 https://imgur.com/a/x6FFD5i
dssxzuxc
5 天前
@635925926 #25 0.1.2 版本已经修复了这个问题了。
除此之外还有相关的 3 个 pr ,都是用的 toFixed ,简单易懂可以去除一堆边界条件,但是作者都没有接受,依旧采用土法硬算舍入值。
我对浮点计算没有深入研究,理论上 toFixed 处理 x.xxx9 和 x.xxx0 是完全正确的,而作者看起来似乎在硬扣性能,只有某些条件下才会回退到 toFixed 。
作者的代码实现还有个多余的
if (result === '0') {
result = '0'
}
完全没看懂在干啥
现在我是选了个其中一个 fork ,copy 一下放进 utils 里。
UnluckyNinja
5 天前
@bli22ard #24 3000004/1000000 得来的可不可以?来自于网络的数据源很难理解吗?你管人家怎么来的,现在问题就是要展示这个数据,而你非要给计算上高精度库,关键是这个情景下就不涉及计算啊。
楼主热得快炸了,你就非得让楼主开空调?
UnluckyNinja
5 天前
@bli22ard #24 不过这么多人都看错,不怪你,得怪作者毫无必要地放了很多计算过程当作例子,网站文本存在误导,“修复浮点精度问题”但实际上只是显示上,而不是给出一个精确的计算结果。
然后 11 楼举了的例子也有一定误导,我用高精度库了更可能是因为我需要准确的结果,而不是为了数字转字符串看起来好看,这种情况下根本没有可比性。
这个库本身就是只有 number 类型到 string 类型转换,这么一个目的和功能。给定一个数字,返回一个字符串,就这么简单,甭管输入哪里来的,用户提供的,库作者想管也管不了。做 OJ 的时候也没人问 input 怎么来的吧。

不过本来我也不太看好这个库,为了这点功能徒增太多了复杂实现,
如果本身就要精度正确,那直接上精度库就好了,
如果要裁剪小数部分,那 toFixed 就可以了,去末尾 0 那就再加个正则替换。
如果为了智能判断高熵部分并展示……我不知道什么情况下会有这样一个需求,为什么要去在乎一个比 epsilon 小很多的噪音,就算如此,展示比 epsilon 小的值,为什么要做字符比较而不是基于数学方式去判断(例如 for 循环递增提取 5 位移到小数点后,tofixed(5)判断是否等于 1 或 0 ,而不是连续比较 5 个 0 或者 5 个 9 )
我很怀疑原作者的精神状态……
bli22ard
4 天前
UnluckyNinja
4 天前
@bli22ard #30 是的这些全是误导,他又不处理计算,都是 js 运行时自己计算,运算结果作为真正参数调用这个库函数,放这些算式纯纯误导。
他本身就是想解决“显示”有精度误差的数字的问题(作为其中一个功能但不是唯一功能),但正常人都会去想引入高精度库直接解决精度问题,而引入高精度库并不能解决“输入本身是一个有噪音部分小数的显示问题”,which 正是这个库“真正想解决的问题”(尽管他的实现让人感觉是不是被 AI 带坏了)
但愿你绕过来了
heiya
4 天前
@mrlmh00 #7 银行家舍入法

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

https://ex.noerr.eu.org/t/1154410

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

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

© 2021 V2EX