go - 1 位和 2 位小数之间的舍入差
问题描述
[Ed:重新措辞 - 很抱歉最初的措辞令人困惑。还要感谢所有建议使用整数的人,但出于几个原因,我必须使用float64
.]
我有一个浮点值,如果超过 100,我想四舍五入到小数点后 1,如果超过 1000,我想四舍五入到小数点后,否则四舍五入到小数点后 2 位。这有效:
func r(f float64) float64 {
if f >= 999.5 {
return math.Round(f)
}
if f >= 99.95 {
return math.Round(f*10) / 10
}
return math.Round(f*100) / 100
}
但我想知道这是否会更好:
func r(f float64) float64 {
if f >= 999.5 {
return math.Round(f)
}
if f*10 >= 999.5 { // **** only changed line ****
return math.Round(f*10) / 10
}
return math.Round(f*100) / 100
}
这更安全,因为 99.95 没有使用二进制指数的浮点精确表示。(我相信 Go 语言需要使用具有二进制指数的 IEEE fp 格式。) 999.5完全可以表示为 fp 值。
但是,我的测试(使用math.NextAfter()
)表明第一个解决方案对于从 99.94999999 到 99.95000001 的所有值都非常有效。第一个问题:我过度担心。
第二种解决方案的问题是我担心f*10
可能会被评估两次。第二个问题:是否有任何保证优化器将确保它只执行一次。
解决方案
如果您担心额外的乘法,而不是依赖优化器,您可以通过以下方式将其拉出:
func r(f float64) float64 {
if f >= 999.5 {
return math.Round(f)
}
f *= 10
if f >= 999.5 {
return math.Round(f) / 10
}
f *= 10
return math.Round(f) / 100
}
推荐阅读
- typescript - 开玩笑的打字稿 - 模拟日期构造函数
- python - 如何让while循环运行?
- php - 通过 PHP discord oauth2(cookie?)保持登录状态
- cron - 如何在 Plesk 中输入 Mailwizz cron 作业?
- pandas - Pandas - 索引包含缺失条目的 DataFrame 时出现意外结果
- sql - SQL Server 查询过滤器的顺序很慢
- java - 初学者java迭代arraylist方法删除和计数
- python-3.x - 将字典数据表单中的熊猫数据框列解析为每个字典键的新列
- laravel - Laravel - 使用其他策略授权
- c++ - vector::_M_range_check: __n (即 1) >= this->size() (即 1)