golang高精度十进制数扩展包decimal用法

news/2025/2/22 19:42:55/

在Go语言中,没有内置的十进制数(decimal)类型或相关的标准库。然而,有一些第三方包可用于处理十进制数,其中比较常用的是decimal包。

decimal包提供了一个big.Float的子类型decimal.Decimal,可以用于表示和操作十进制数。它具有更高的精度和更大的范围,可以处理任意精度的十进制数。

golang中的任意精度定点十进制数扩展包decimal。

demimal包特点:

  • 零值为0,无需初始化即可安全使用
  • 不损失精度的加法、减法、乘法
  • 以指定精度除法
  • 数据库/sql序列化/反序列化
  • JSON 和 XML 序列化/反序列化

要使用decimal包,首先需要确保已经安装了该包。你可以通过以下命令安装该包:

一、安装方法:

go get github.com/shopspring/decimal

二、安装要求

decimal包需要 Go 版本 >=1.7

三、使用方法

package mainimport ("fmt""github.com/shopspring/decimal"
)func main() {price, err := decimal.NewFromString("136.02")if err != nil {panic(err)}quantity := decimal.NewFromInt(3)fee, _ := decimal.NewFromString(".035")taxRate, _ := decimal.NewFromString(".08875")subtotal := price.Mul(quantity)preTax := subtotal.Mul(fee.Add(decimal.NewFromFloat(1)))total := preTax.Mul(taxRate.Add(decimal.NewFromFloat(1)))fmt.Println("Subtotal:", subtotal)                      // Subtotal: 408.06fmt.Println("Pre-tax:", preTax)                         // Pre-tax: 422.3421fmt.Println("Taxes:", total.Sub(preTax))                // Taxes: 37.482861375fmt.Println("Total:", total)                            // Total: 459.824961375fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875
}

安装完成后,你可以在你的Go代码中导入该包并使用decimal.Decimal类型。以下是一个简单的示例代码:

package main  import (  "fmt"  "gopkg.in/decimal.v1"  
)  func main() {  // 创建一个十进制数  d := decimal.New(12345, 2) // 12345精确到小数点后2位  // 输出十进制数的字符串表示  fmt.Println(d.String()) // 输出:"12.34"  // 进行十进制数的四则运算  a := decimal.New(10, 0)   // 整数10  b := decimal.New(20, 2)   // 十进制数20.00  c := decimal.New(30, 2)   // 十进制数30.00  d = a.Add(b, c)          // 加法运算  e := a.Sub(b, c)         // 减法运算  f := a.Mul(b, c)         // 乘法运算  g := a.Quo(b, c)         // 除法运算  // 输出结果  fmt.Println(d.String())   // 输出:"31.00"  fmt.Println(e.String())   // 输出:"-10.00"  fmt.Println(f.String())   // 输出:"2200.00"  fmt.Println(g.String())   // 输出:"0.50"  
}

这个示例展示了如何创建十进制数、进行四则运算以及输出字符串表示。decimal包还提供了其他一些方法和函数,你可以根据需要进一步探索和使用。

四、FAQ

为什么不直接使用 float64 呢?

因为 float64(实际上是任何二进制浮点类型)无法精确表示 0.1 等数字。

你为什么不直接使用big.Rat呢?

big.Rat 适合表示有理数,但 Decimal 更适合表示金钱。 为什么? 这是一个(人为的)示例:

假设您使用 big.Rat,并且有两个数字 x 和 y,都代表 1/3,并且 z = 1 - x - y = 1/3。 如果打印出每个数字,则字符串输出必须在某个地方停止(为简单起见,假设它停止在 3 个小数位处),因此您将得到 0.333、0.333 和 0.333。 但另外的0.001去哪儿了呢?
对于 Decimal,打印出来的字符串准确地表示数字。 因此,如果 x = y = 1/3(精度为 3),它们实际上等于 0.333,而当 z = 1 - x - y 时,z 将等于 0.334。 没有钱下落不明!

你还是要小心。 如果你想将一个数字分成 N 3 种方式,你不能只将 N/3 发送给三个不同的人。 您必须选择一个发送 N - (2/3*N) 给。 该人将收到剩余的一分钱的一小部分。

但是,使用 Decimal 比使用 big.Rat 容易得多。

为什么 API 与 big.Int 的不相似?

big.Int 的 API 旨在减少内存分配数量以实现最佳性能。 这对于它的用例来说是有意义的,但代价是 API 很笨拙并且容易被误用。

例如,要添加两个 big.Int,您可以执行以下操作:z := new(big.Int).Add(x, y)。 不熟悉此 API 的开发人员可能会尝试执行 z := a.Add(a, b)。 这会修改 a 并将 z 设置为 a 的别名,这是他们意想不到的。 它还将任何其他别名修改为 a。

相比之下,使用小数就很难犯这样的错误。 Decimal 的行为与其他 Go 数字类型类似:即使 a = b 不会将 b 深度复制到 a 中,但也不可能修改 Decimal,因为所有 Decimal 方法都会返回新的 Decimal,并且不会修改原始的 Decimal。 缺点是这会导致额外的分配,因此 Decimal 的性能较差。 我的假设是,如果您使用小数,您可能更关心正确性而不是性能。


http://www.ppmy.cn/news/1090450.html

相关文章

MySql学习笔记12——数据库设计三范式

数据库设计三范式 第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分。 第二范式:建立在第一范式之上,要求所有非主键字段必须完全依赖主键,不能部分依赖 第三范式:建立在第二范式之上&#…

字节对齐(C++,C#)

C#字节对齐示例 结构体定义 [StructLayoutAttribute(LayoutKind.Sequential, CharSet CharSet.Ansi, Pack 1)],这是C#引用非托管的C/C的DLL的一种定义定义结构体的方式,主要是为了内存中排序,LayoutKind有两个属性Sequential和Explicit&a…

如何将MySQL中指定的表结构同步到人大金仓数据库

场景 刚开始做数据库适配的时候,这是一个棘手的问题,因为MySQL的库里,表结构,字段都是最新的,但是金仓的库,全是旧版本的表结构。需要把我们模块的表结构,同步到金仓中。 虽然金仓有数据库同步工具,但是直接把所有表都给同步过来,难免会影响到其他模块。 然后…

scala基础

scala 基础 1. scala简介 scala是运行在 JVM 上的多范式编程语言,同时支持面向对象和面向函数编程早期scala刚出现的时候,并没有怎么引起重视,随着Spark和Kafka这样基于scala的大数据框架的兴起,scala逐步进入大数据开发者的眼帘…

JAVA 函数式接口与lambda

1.函数式定义 什么是函数式接口呢?听起来很绕,我们可以这样理解: 可以接收lambda函数的接口,就可以叫做函数式接口。 注意一个函数式接口里,只允许定义一个抽象方法。 在java里可以用FunctionalInterface注解来标注…

一:高通量虚拟筛选技术与中药/天然产物挖掘药效分子专题

一:高通量虚拟筛选技术与中药/天然产物挖掘药效分子专题 第一天上午 1.筛选策略基本原理及流程 1.运用全新筛选策略快速发现新药先导化合物 1.1全新筛选策略的基本原理 1.1.1基于药效团模型的虚拟筛选方法 1.1.2基于分子对接的虚拟筛选方法 1.1.3全新先导化合物的筛…

《人生苦短——我学Python》条件判断->双向选择(if--else)

今天我们来学习双向选择判断。顾名思义,双向就是两种选择选其一,即if----else。如果If的条件不成立,则执行else下的语句,否则执行if下面的语句。显然,它们是互斥的!下面就让我们来详细看看吧! 文…

【构造】CF Edu 12 D

Problem - D - Codeforces 题意: 思路: 这种题一定要从小数据入手,不然很有可能走歪思路 先考虑n 1的情况,直接输出即可 然后是n 2的情况,如果相加是质数,就输出2个,否则就输出一个 然后…