Go 加、减、乘、除基本运算

简介

Go 属于强类型语言,各种数值类型不允许直接进行运算,和PHP、Python、JavaScript等弱类型而言,在运算过程中比较麻烦,需要对数据进行转换成同类型才可以运算,若是遇到整型的除法运算(10 / 3 = 3),会丢失掉小数点之后数值,精度会大大降低,要想可以保留小数点,就需要对数据类型进行转换成Float64或Float32,才能进行操作,若是每次运算都是如此操作的话,对编程就比较麻烦,所以一般都会对加减乘除这样的简单运算做逻辑封装,后期只需调用对应的方法函数即可。

代码示例

针对加减乘除做了以下封装

加法

// Add 加法,两数及以上的数值累计相加之和,并保留小数点后两位
// Example:
// Add(100, 2000, 2, 100.01111)
// Output: 2200.01
func Add(x, y interface{}, decimal float64, z ...interface{}) float64 {
	sum := Float64(x) + Float64(y)
	if len(z) > 0 {
		for _, v := range z {
			sum += Float64(v)
		}
	}
	return Scale(sum, decimal)
}

减法

// Sub 减法,两数及以上的数值累计之差,并保留小数点后两位
// Example:
// Sub(100, 2000, 2, 100.01111)
// Output: -2000.01
func Sub(x, y interface{}, decimal float64, z ...interface{}) float64 {
	s := Float64(x) - Float64(y)
	if len(z) > 0 {
		for _, v := range z {
			s -= Float64(v)
		}
	}
	return Scale(s, decimal)
}

乘法

// Mul 乘法,两数及以上的数值乘积,并保留小数点后两位
// Example:
// Mul(100, 2000, 2, 100.01111)
// Output: 2.0002222e+07
func Mul(x, y interface{}, decimal float64, z ...interface{}) float64 {
	s := Float64(x) * Float64(y)
	if len(z) > 0 {
		for _, v := range z {
			s *= Float64(v)
		}
	}
	if s == 0 {
		return 0
	}
	return Scale(s, decimal)
}

除法

// Div 除法, 两数相除
// Example:
// Sub(999, 8989.5645, 2)
// Output: 0.11
func Div(x, y interface{}, decimal float64) float64 {
	if Float64(y) == 0 || Float64(x) == 0 {
		return 0
	}
	s := Float64(x) / Float64(y)
	return Scale(s, decimal)
}

转换函数

  1. 小数点保留转换设置函数
// Scale 保留小数点-四舍五入算法
// Example:
// Scale(98.88888, 2) 保留两位小数
// Output: 98.89
func Scale(s, decimal float64) float64 {
	// 保留小数点,注:避免小数点小于等于0,计算错误
	var d float64 = 1
	if decimal > 1 {
		d = math.Pow(10, decimal) // 10的N次方
	}
	return math.Round(s*d) / d
}
  1. 数据类型浮点型内部转换函数
// Float64 转换float64
func Float64(any interface{}) float64 {
	if any == nil {
		return 0
	}
	switch value := any.(type) {
	case float64:
		return value
	case float32:
		return float64(value)
	case uint:
		return float64(value)
	case uint8:
		return float64(value)
	case uint32:
		return float64(value)
	case uint16:
		return float64(value)
	case int:
		return float64(value)
	case int8:
		return float64(value)
	case int16:
		return float64(value)
	case int32:
		return float64(value)
	case int64:
		return float64(value)
	case string:
		v, _ := strconv.ParseFloat(value, 64)
		return v
	default:
		return 0
	}
}

逻辑解析:

  1. 定义Add、Sub、Mul、Div函数,x,y参数定义interface接口类型,允许接收整型、浮点型、字符串类型,采用内部类型转换逻辑,把所有参数转成浮点型进行运算,decimal:设置允许保留多少位小数,z:为可变函数,同样设置为interface接口类型,允许多个数值进行运算,但不强制输入(除法除外);
  2. Float64函数,把interface接口类型,统一转成float64类型进行运算,输出的数据类型也是float64,减少外部手动转的麻烦
  3. Scale函数:设置本次运算需要保留的小数点位数,为避免出现输入,小于等于0的情况下,默认不保留小数点,返回float64类型结果

完整代码示例

package util

import (
	"math"
	"strconv"
)

// Add 加法,两数及以上的数值累计相加之和,并保留小数点后两位
// Example:
// Add(100, 2000, 2, 100.01111)
// Output: 2200.01
func Add(x, y interface{}, decimal float64, z ...interface{}) float64 {
	sum := Float64(x) + Float64(y)
	if len(z) > 0 {
		for _, v := range z {
			sum += Float64(v)
		}
	}
	return Scale(sum, decimal)
}

// Sub 减法,两数及以上的数值累计之差,并保留小数点后两位
// Example:
// Sub(100, 2000, 2, 100.01111)
// Output: -2000.01
func Sub(x, y interface{}, decimal float64, z ...interface{}) float64 {
	s := Float64(x) - Float64(y)
	if len(z) > 0 {
		for _, v := range z {
			s -= Float64(v)
		}
	}
	return Scale(s, decimal)
}

// Mul 乘法,两数及以上的数值乘积,并保留小数点后两位
// Example:
// Mul(100, 2000, 2, 100.01111)
// Output: 2.0002222e+07
func Mul(x, y interface{}, decimal float64, z ...interface{}) float64 {
	s := Float64(x) * Float64(y)
	if len(z) > 0 {
		for _, v := range z {
			s *= Float64(v)
		}
	}
	if s == 0 {
		return 0
	}
	return Scale(s, decimal)
}

// Div 除法, 两数相除
// Example:
// Sub(999, 8989.5645, 2)
// Output: 0.11
func Div(x, y interface{}, decimal float64) float64 {
	if Float64(y) == 0 || Float64(x) == 0 {
		return 0
	}
	s := Float64(x) / Float64(y)
	return Scale(s, decimal)
}

// Scale 保留小数点-四舍五入算法
// Example:
// Scale(98.88888, 2) 保留两位小数
// Output: 98.89
func Scale(s, decimal float64) float64 {
	// 保留小数点,注:避免小数点小于等于0,计算错误
	var d float64 = 1
	if decimal > 1 {
		d = math.Pow(10, decimal) // 10的N次方
	}
	return math.Round(s*d) / d
}

// Float64 转换float64
func Float64(any interface{}) float64 {
	if any == nil {
		return 0
	}
	switch value := any.(type) {
	case float64:
		return value
	case float32:
		return float64(value)
	case uint:
		return float64(value)
	case uint8:
		return float64(value)
	case uint32:
		return float64(value)
	case uint16:
		return float64(value)
	case int:
		return float64(value)
	case int8:
		return float64(value)
	case int16:
		return float64(value)
	case int32:
		return float64(value)
	case int64:
		return float64(value)
	case string:
		v, _ := strconv.ParseFloat(value, 64)
		return v
	default:
		return 0
	}
}

总结

  1. 以上代码,可以根据自己业务实际情况进行修改使用,只是提供一个逻辑供大家参考,本次操作用到库(math、strconv),返回的数据以四舍五入后的float64值返回,支持所有数值类型和数字字符串类型使用,注:若是涉及大数字运算,需用引用bigMath进行处理,但一般情况下根本不会有大额数字运算的方法,所以以上函数基本可以处理大部分运算场景,可以直接使用,若是传入非数字字符串或其他非数值类型,默认返回0,请根据实际业务修改;
  2. 转换返回0的示例如下:
a := "12312321321"
b := "24234234234.44"
c := "242342423dd"
d := "dd348783434.44"
// Output:调用Float64(输出如下)
// a =  12312321321
// b =  24234234234.44
// c和d = 0

只有全数字类型才能转换成float64类型,所以请注意字符串类型的数字,不能含有不能转换的特殊字符

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bobo-rs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值