四舍五入详解

四舍五入详解(这不是你认知的四舍五入)

很详细,有很多Demo并提供了在线运行地址。想搞明白得自己多试试

三种规则

  1. 标准四舍五入
  2. 四舍五基础上正负不一样
  3. 银行家算法

一、标准四舍五入

代表工具
  1. go语言的decimal运算库
  2. numbro库的format(v2.3.1版本后),PR详情
描述

和名字一样,就是我们大部分人认知的四舍五入

例子

10.5 ==> 11
-10.5 ==> -11
10.885 ==> 10.89 (保留两位)
-10.885 ==> -10.89 (保留两位)

实操

go在线运行地址(需要翻墙)

package main
import (
	"fmt"
	"github.com/shopspring/decimal"
)
func main() {
	var f = []float64{10.5, -10.5, 10.885, -10.885}
	for _, v := range f {
		// decimal库
		fmt.Println(v, "==> decimal库", decimal.NewFromFloat(v).StringFixed(2))
		fmt.Println("--------")
	}
}

decimal标准四舍五入

二、四舍五入基础上正负不一样

代表工具
  1. Math.round()
  2. numbro库(v2.3.1版本前)通过浏览器端运行第三方库的插件将numbro库装到浏览器环境中即可运行
描述
  1. 正数按照严标准的四舍五入来
  2. 负数四舍六入,五后大于0则入,五后为0就舍
例子

10.5 ==> 11
-10.5 ==> -10
-10.51 ==> -11

实操
const nums = [10.5, -10.5, -10.51];
const test = () => {
  nums.forEach(item => console.log(`${item} ==>  Math.round ${Math.round(item)}`));
};
test();

正负四舍五入不一样

const nums = [10.5, -10.5, 10.885, -10.885, -10.8851];
const test = () => {
  nums.forEach(item => console.log(`${item} ==> numbro库 ${numbro(item).format('0.00')}`));
};
test();

numbro库

三、银行家算法

代表工具
  1. java可配置使用
  2. C#的进位,VB.net
  3. 很多博客上说 toFixed 和 Go 自带的也是(我表示怀疑,起码官方没说,详情见下方标题四的内容)
描述
  1. 四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一
  2. 银行家舍入是IEEE规定的小数舍入标准之一,也是IEEE目前规定中最优秀的舍入方法,因此所有符合 IEEE 标准的语言都应该实现这种算法
例子

9.8249 ==> 9.82(四舍)
9.82671 ==> 9.83(六入)
9.8351 ==> 9.84(五后非零就进一)
9.82501 ==> 9.83(五后非零就进一)
9.8250 ==> 9.82(五后为零看奇偶,五前为偶应舍去)
9.8350 ==> 9.84(五后为零看奇偶,五前为奇要进一)

实操

自己有兴趣可以试试,我没在线运行试,不是搞后端的

四、toFixed 和 Go自带的fmt

描述

哪个都不是,没找到规律,可能是银行家算法,但是由于浮点数不能精确地用二进制表示所有小数。这可能会导致意外的结果

结论

经尝试 toFixed 和 go 是一样的,从结果来看不是银行家算法,但可能设计的时候是银行家算法,但是由于浮点数不能精确地用二进制表示所有小数而产生了意外。
toFixed  MDN  说明
在这里插入图片描述

toFixed
实操

toFixed 在线运行地址 结论并不是5后为0看奇偶

//程序运行完成时一定要有输出语句,本工具才能正确展示运行结果。 
const list = [989.075,989.175,989.275,989.375,989.475,989.575,989.675,989.775,989.875,989.975];
const list1 = [989.065,989.165,989.265,989.365,989.465,989.565,989.665,989.765,989.865,989.965];
const yhj = [9.8249, 9.82671, 9.8351, 9.82501, 9.8250, 9.8350];

list.forEach((item)=>{console.log(`${item} ==> ${item.toFixed(2)}`)})
console.log('--------------')
list1.forEach((item)=>{console.log(`${item} ==> ${item.toFixed(2)}`)})
console.log('--------------')
//银行家算法:四舍六入,五后不为0则如,为零看五前,前一个奇数进位,偶数舍去
console.log('银行家算法:四舍六入,五后不为0则如,为零看五前,前一个奇数进位,偶数舍去');
yhj.forEach((item)=>{console.log(`${item} ==> ${item.toFixed(2)}`)})

toFixed 例子

Go的fmt
实操

go在线例子

package main
import (
	"fmt"
	"github.com/shopspring/decimal"
)
func main() {
	var f = []float64{989.075, 989.175, 989.275, 989.375, 989.475, 989.575, 989.675, 989.775, 989.875, 989.975}
	var f1 = []float64{989.065, 989.165, 989.265, 989.365, 989.465, 989.565, 989.665, 989.765, 989.865, 989.965}
	var yhj = []float64{9.8249, 9.82671, 9.8351, 9.82501, 9.8250, 9.8350}
	for _, v := range f {
		fmt.Print(v,"==>",decimal.NewFromFloat(v).StringFixed(2))
		fmt.Printf("  go自带的fmt %0.2f\n", v)
	}
	fmt.Println("******************************")
	for _, v1 := range f1 {
		fmt.Print(v1,"==> decimal库",decimal.NewFromFloat(v1).StringFixed(2) )
		fmt.Printf("  go自带的fmt %0.2f\n", v1)
	}
	fmt.Println("******************************")
	for _, v2 := range yhj{
		fmt.Print(v2,"==>",decimal.NewFromFloat(v2).StringFixed(2))
		fmt.Printf("  go自带的fmt %0.2f\n", v2)
	}

}

go自带的fmt

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值