当前位置:首页 > 文章列表 > Golang > Go问答 > 对于货币应用程序来说,使用整数作为小数系数而不是浮点数是个好主意吗?

对于货币应用程序来说,使用整数作为小数系数而不是浮点数是个好主意吗?

来源:stackoverflow 2024-04-01 22:21:36 0浏览 收藏

Golang小白一枚,正在不断学习积累知识,现将学习到的知识记录一下,也是将我的所得分享给大家!而今天这篇文章《对于货币应用程序来说,使用整数作为小数系数而不是浮点数是个好主意吗?》带大家来了解一下##content_title##,希望对大家的知识积累有所帮助,从而弥补自己的不足,助力实战开发!


问题内容

我的应用程序需要小数数量乘以货币价值。

例如,$65.50 × 0.55 小时 = $36.025(四舍五入为 $36.03)。

我知道浮点数不应该用来表示金钱,因此我将所有货币值存储为美分。 $65.50 在上式中存储为 6550(整数)。

对于小数系数,我的问题是 0.55 没有 32 位浮点表示。在上面的用例中,0.55 小时 == 33 分钟 ,因此 0.55 是我的应用程序需要准确考虑的特定值的示例。 0.550000012 的浮点表示是不够的,因为用户不会理解附加的 0.000000012 来自哪里。我不能简单地在 0.550000012 上调用舍入函数,因为它会舍入到整数。

乘法解决方案

为了解决这个问题,我的第一个想法是将所有数量存储为整数并乘以×1000。因此用户输入的0.55在存储时将变成550(整数)。所有计算都将在没有浮点数的情况下进行,然后在向用户呈现结果时简单地除以 1000(整数除法,而不是浮点数)。

  • 我意识到这将永久限制我的小数点后 3 位 精确。如果我认为 3 足以满足我的一生 应用程序,这种方法有意义吗?

  • 如果我使用整数除法,是否存在潜在的舍入问题?

  • 这个过程有名字吗? 编辑:正如@SergGr所示,这是定点算术。

  • 有更好的方法吗?

编辑:

我应该澄清一下,这不是特定时间的。它适用于一般数量,例如 1.256 磅面粉 1 sofa0.25 小时 (想想发票)。

我在这里尝试复制的是 Postgres 的 extra_float_digits = 0 功能的更精确版本,如果用户输入 0.55 (float32),数据库将存储 0.550000012 但在查询结果时返回 0。 55 这似乎正是用户输入的内容。

我愿意将此应用程序的精度限制为小数点后 3 位(这是商业问题,而不是科学问题),因此这就是让我考虑使用 × 的原因。 1000 方法。

我正在使用 Go 编程语言,但我对通用跨语言解决方案感兴趣。


解决方案


注意:这是按照 Matt 的要求将不同的评论合并为一个连贯的答案的尝试。

TL;DR

  1. 是的,这种方法很有意义,但很可能不是最佳选择
  2. 是的,存在舍入问题,但无论您使用哪种表示形式,都不可避免地会出现一些问题
  3. 您建议使用的名称为 Decimal fixed point numbers
  4. 我认为是的,有一个更好的方法,那就是为您的语言使用一些标准或流行的 decimal floating point numbers 库(Go 不是我的母语,所以我不能推荐一个)

在 PostgreSQL 中,最好使用 numeric (例如 Numeric(15,3) 之类的东西),而不是 float4/float8extra_float_digits 的组合。实际上,这就是 PostgreSQL doc on Floating-Point Types 中的第一项所建议的内容:

  • 如果您需要精确的存储和计算(例如货币金额),请改用 numeric 类型。

有关如何存储非整数的更多详细信息

首先有一个基本事实,即 [0;1] 范围内有无限多个数字,因此显然无法将每个数字存储在任何有限的数据结构中。这意味着您必须做出一些妥协:无论您选择哪种方式,都会有一些数字您无法准确存储,因此您必须进行舍入。

另一个重要的一点是,人们习惯于基于 10 的系统,在该系统中,只有 2^a*5^b 形式的数字除法结果可以用有限位数表示。对于每个其他有理数,即使您以某种方式将其存储为精确的形式,您也必须在格式化阶段进行一些截断和舍入以供人类使用。

存储数字的方法可能有无数种。在实践中,只有少数被广泛使用:

  • floating point numbers 具有两个主要的二进制分支(这是当今大多数硬件本身实现的内容,也是大多数语言支持的内容,如 floatdouble)和 decimal。这是存储尾数和指数的格式(可以是负数),所以数字是 mantissa * base^exponent (我省略了符号,只是说它在逻辑上是尾数的一部分,尽管实际上它通常是单独存储的)。二进制与十进制由 base 指定。例如,0.5 将以二进制形式存储为一对 (1,-1),即 1*2^-1,以十进制形式存储为一对 (5,-1),即 5*10^-1。理论上,您也可以使用任何其他基数,但实际上只有 2 和 10 作为基数才有意义。

  • fixed point numbers,二进制和十进制的除法相同。这个想法与浮点数相同,但所有数字都使用一些固定指数。您建议的实际上是一个十进制定点数,指数固定为 -3。我见过在一些没有内置浮点数支持的嵌入式硬件上使用二进制定点数,因为可以使用整数算术以合理的效率实现二进制定点数。至于十进制定点数,实际上实现起来并不比十进制浮点数容易多少,但灵活性却低得多。

  • 有理数格式,即该值存储为一对 (p, q),表示 p/q(通常是 q>0,因此符号存储在 p 中,并且 p=0、q=1 表示 zqbc) zqb0或 gcd(p,q) = 1 对于每个其他数字)。通常这首先需要一些大整数算术才有用(这里是 math.big.Rat 的 Go 示例)。实际上,这对于某些问题可能是一种有用的格式,人们经常忘记这种可能性,可能是因为它通常不是标准库的一部分。另一个明显的缺点是,正如我所说,人们不习惯用有理数来思考(你能轻松比较 123/456213/789 哪个更大吗?),所以你必须将最终结果转换为其他形式。另一个缺点是,如果您有很长的计算链,内部数字(pq)可能很容易变成非常大的值,因此计算速度会很慢。存储计算的中间结果仍然可能有用。

实际上,也分为任意长度和固定长度表示。例如:

实际上,我想说,解决您的问题的最佳解决方案是一些足够大的固定长度浮点十进制表示(例如.Net decimal)。任意长度的实现也可以工作。如果您必须从头开始实现,那么您对固定长度定点十进制表示的想法可能没问题,因为它是您自己实现的最简单的事情(比以前的替代方案容易一点),但它可能会成为某些方面的负担存储结果的另一种解决方案是使用值的有理形式。您可以用两个等于 p/q 的整数值来解释该数字,这样 pq 都是整数。因此,您可以对数字进行更精确的计算,并使用两个整数格式的有理数进行一些数学运算。

今天关于《对于货币应用程序来说,使用整数作为小数系数而不是浮点数是个好主意吗?》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

版本声明
本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
破解 Java JCA 密码迷阵,成为加密大师破解 Java JCA 密码迷阵,成为加密大师
上一篇
破解 Java JCA 密码迷阵,成为加密大师
如何使用 sqlx 插入给定的时间戳
下一篇
如何使用 sqlx 插入给定的时间戳
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 谱乐AI:青岛艾夫斯科技的多模型AI音乐生成工具
    谱乐AI
    谱乐AI是由青岛艾夫斯科技有限公司开发的AI音乐生成工具,采用Suno和Udio模型,支持多种音乐风格的创作。访问https://yourmusic.fun/,体验智能作曲与编曲,个性化定制音乐,提升创作效率。
    4次使用
  • Vozo AI:超真实AI视频换脸工具,提升创意内容制作
    Vozo AI
    探索Vozo AI,一款功能强大的在线AI视频换脸工具,支持跨性别、年龄和肤色换脸,适用于广告本地化、电影制作和创意内容创作,提升您的视频制作效率和效果。
    4次使用
  • AIGAZOU:免费AI图像生成工具,简洁高效,支持中文
    AIGAZOU-AI图像生成
    AIGAZOU是一款先进的免费AI图像生成工具,无需登录即可使用,支持中文提示词,生成高清图像。适用于设计、内容创作、商业和艺术领域,提供自动提示词、专家模式等多种功能。
    4次使用
  • Raphael AI:Flux.1 Dev支持的免费AI图像生成器
    Raphael AI
    探索Raphael AI,一款由Flux.1 Dev支持的免费AI图像生成器,无需登录即可无限生成高质量图像。支持多种风格,快速生成,保护隐私,适用于艺术创作、商业设计等多种场景。
    4次使用
  • Canva可画AI生图:智能图片生成新选择
    Canva可画AI生图
    Canva可画AI生图利用先进AI技术,根据用户输入的文字描述生成高质量图片和插画。适用于设计师、创业者、自由职业者和市场营销人员,提供便捷、高效、多样化的视觉素材生成服务,满足不同需求。
    5次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码