wisetc
V2EX  ›  数据库

金额的存储用 long 可以吗

  •  
  •   wisetc · May 30, 2019 · 9641 views
    This topic created in 2563 days ago, the information mentioned may be changed or developed.
    想将金额的数值乘以 1000 然后再存库,方便数据的存储。让前端提交给后端的数据都先乘以 1000,然后后端返回给前端的金额数据是放大了 1000 倍的,显示的时候再让前端处理,除以 1000,后台不用对金额做任何处理,哈哈哈。我真是越来越佩服我自己。
    各位后端大佬,怎么看。
    81 replies    2019-05-31 14:17:20 +08:00
    adzchao
        1
    adzchao  
       May 30, 2019   ❤️ 1
    完全可以 看精确到多少位 后端就是这么搞的
    surfire91
        2
    surfire91  
       May 30, 2019
    精度够的话当然可以。
    ezksdo
        3
    ezksdo  
       May 30, 2019
    用整数,存的时候乘 100
    mawenjie
        4
    mawenjie  
       May 30, 2019
    这不是常识吗,你敢用浮点数搞?
    tabris17
        5
    tabris17  
       May 30, 2019
    既然有 decimal 为什么不用?
    wisetc
        6
    wisetc  
    OP
       May 30, 2019
    各位大佬,其实我是前端,乘以 1000,然后再除以 1000,好烦哦,再前端搞来搞去太容易出错了,我就是吐个槽,看看有没有更高级的做法,比如在数据库前面加个网,好比过了就是天上一天地下一年
    neuthself
        7
    neuthself  
       May 30, 2019
    《高性能 MySQL 》也有讲到类似的方式,可以有但感觉没必要,直接用 decimal 吧
    jifengg
        8
    jifengg  
       May 30, 2019
    金额,我一般都是统一单位为“分”,因为金额一般要涉及到加减的操作,用整数能保证精度。
    RubyJack
        9
    RubyJack  
       May 30, 2019
    decimal
    TheCure
        10
    TheCure  
       May 30, 2019
    这不是大学就学的么..
    keepeye
        11
    keepeye  
       May 30, 2019
    有些情况下要对金额做除法,就会出现小数了,如果不精确的话可能会导致金额出现偏差 1 分
    zgl263885
        12
    zgl263885  
       May 30, 2019 via iPhone
    我时间戳都用的 long,前端拿到后自己再处理下。可读性和性能能好的一匹。
    wolfie
        13
    wolfie  
       May 30, 2019
    别像摩拜用 int 就行
    txwd
        14
    txwd  
       May 30, 2019
    见过用 4 位小数的,天坑
    hailiang88
        15
    hailiang88  
       May 30, 2019 via iPhone
    前端操作金额会有精度问题,需要单独处理
    nszm
        16
    nszm  
       May 30, 2019   ❤️ 1
    乘除这种给后端操作,前端这个搞不是搞事情吗
    gogogogogo
        17
    gogogogogo  
       May 30, 2019
    iOS 端会有精读问题
    rockyou12
        18
    rockyou12  
       May 30, 2019   ❤️ 3
    后端这样存其实算是常规操作。前端好像有个 decimal.js (好像叫这个)的库可以做精确的数字运算,我觉得 lz 可能需要的是这个
    swulling
        19
    swulling  
       May 30, 2019 via iPhone
    钱一定要用整数存…存成分就行了
    9151
        20
    9151  
       May 30, 2019   ❤️ 5
    楼主在搞什么山寨币?
    peterontheway
        21
    peterontheway  
       May 30, 2019   ❤️ 1
    BigDecimal
    whypool
        22
    whypool  
       May 30, 2019
    用整数,存分或者厘
    Caballarii
        23
    Caballarii  
       May 30, 2019
    上面说存成分的都是没做过利率计算的吧
    indingpig
        24
    indingpig  
       May 30, 2019   ❤️ 1
    计算的话还是交给后台计算吧,前端计算精度有可能出问题的。比如长度超过 17 位的数,精度就开始丢失,前端最大和最小的安全整数是正负 2 的 53 次方-1
    tonghuashuai
        25
    tonghuashuai  
       May 30, 2019
    Decimal
    julyclyde
        26
    julyclyde  
       May 30, 2019   ❤️ 1
    老老实实用 currency 类型,别找事
    qiyuey
        27
    qiyuey  
       May 30, 2019 via Android
    一般是用分
    shm7
        28
    shm7  
       May 30, 2019 via iPhone
    一看就不知道有个 format 叫 bank format (小数点后两位),后面的就可以拿来 tanwu 了
    SingeeKing
        29
    SingeeKing  
    PRO
       May 30, 2019
    为什么是 1000 而不是 100 …… 微信支付就是以分为单位的
    RangerWolf
        30
    RangerWolf  
       May 30, 2019
    谷歌广告的数据就是这么干的~ 你说可以么?

    但是直接用 decimal 个人觉得也不错
    ETiV
        31
    ETiV  
       May 30, 2019 via iPhone
    LZ 好厉害,我都要佩服 LZ
    passerbytiny
        32
    passerbytiny  
       May 30, 2019   ❤️ 2
    @SingeeKing #27 以前虽然现金只到分,但算账的时候要算到厘。严格意义上说,微信支付是有问题的,因为现在现金是只到角的,分、厘都只能用于计算,不能用于最后的支付。
    lithiumii
        33
    lithiumii  
       May 30, 2019
    反正我司用的 float,偶尔出现一些奇幻情况,我都惊了
    JerryCha
        34
    JerryCha  
       May 30, 2019
    我用 String (逃
    troywinter
        35
    troywinter  
       May 30, 2019
    #3 是正解,用整型存储最后处理时除以 100 是常识操作,不应该用其它方式,至于出错的问题 ddd 完全可以解决。
    icebay
        36
    icebay  
       May 30, 2019
    就用 decimal,计算用高精度函数。
    ccming
        37
    ccming  
       May 30, 2019 via iPhone
    @troywinter 汇率怎么处理
    dosmlp
        38
    dosmlp  
       May 30, 2019
    @lithiumii 用 float 也是牛鼻,float 各种运算精度更差
    limuyan44
        39
    limuyan44  
       May 30, 2019 via Android
    真不怕无中丢钱,无中生钱?
    lithiumii
        40
    lithiumii  
       May 30, 2019 via Android
    @dosmlp 是啊,我看到都吐血了
    conn4575
        41
    conn4575  
       May 31, 2019 via Android
    说存分的肯定没真正处理过金额问题,金额不是只有加减好吗,还有除法,用整数肯定存在精度问题,老老实实用 decemal,而且最好要 12 位以上小数
    ericgui
        42
    ericgui  
       May 31, 2019
    应该是按照货币的最小单位
    比如,美元,最小是美分,就应该乘以 100
    人民币,最小是分,乘以 100

    日元和韩元,似乎没有分,就是正整数,1 就是 1 元
    h123123h
        43
    h123123h  
       May 31, 2019
    7/3 这种小数怎么办?特别是参与多次运算,精度问题误差会越来越大,看来楼上的都没做过金额处理啊
    h123123h
        44
    h123123h  
       May 31, 2019
    老老实实用 Bigdecimal
    MonoLogueChi
        45
    MonoLogueChi  
       May 31, 2019 via Android
    @keepeye 所以要多保存一位,控制除法的精确度
    tsui
        46
    tsui  
       May 31, 2019
    @h123123h 正解。。必须只能 BigDecimal,怎么可能用 Decimal
    ytmsdy
        47
    ytmsdy  
       May 31, 2019 via iPhone
    用 long 如果四舍五入没问题的话就用吧!要不然后期对账对死你!
    gavindexu
        48
    gavindexu  
       May 31, 2019 via iPhone
    涉及除法的话,
    能不能加俩字段去保留分子分母?
    一定要存储结果么……🤔
    yemoluo
        49
    yemoluo  
       May 31, 2019
    用!而且一定要要,所有计算都直接用,只有在显示用户看的时候除 100。前端也一样
    toxicant
        50
    toxicant  
       May 31, 2019 via Android
    金额还能让前端处理的吗...
    Ciallo
        51
    Ciallo  
       May 31, 2019
    BigDecimal 吧
    22too
        52
    22too  
       May 31, 2019   ❤️ 3
    decimal 这个才是正解
    1. 万一那天有个人写了一个 bug, 会不会出现金额多了 1000 倍. 无端制造风险
    2. 不要理想的以为,金钱就涉及到加减法,乘除法也是经常出现的
    3. 很多时候,分并不是最小单位,比如 某借呗 按照日万五收取利息, 这样会产生比分更小单位.
    yidinghe
        53
    yidinghe  
       May 31, 2019
    我们是拿分做单位。
    auin
        54
    auin  
       May 31, 2019
    银行一般的精度是:Decimal(18,6) -> 999999999999.999999
    AlloVince
        55
    AlloVince  
       May 31, 2019
    既然大家说钱都是默认以元为单位,就不要做违反直觉的设计
    zealinux
        56
    zealinux  
       May 31, 2019
    存:分子和分母

    298.6734
    分子:2986734
    分母:10000
    chenuu
        57
    chenuu  
       May 31, 2019
    存货币的最小单位
    justicelove
        58
    justicelove  
       May 31, 2019
    不单单要看存储的需要, 还要看计算的需要
    RRRoger
        59
    RRRoger  
       May 31, 2019
    有的国家是 0.001 怎么办 我们支持多货币的
    karllynn
        60
    karllynn  
       May 31, 2019
    用整形没有问题的,用 decimal 也可以,不过 js 的浮点数精度丢失问题好像很严重
    brust
        61
    brust  
       May 31, 2019
    @txwd
    这边有 5 位的
    还是 varchar
    luozic
        62
    luozic  
       May 31, 2019
    小數直接切了?
    wisetc
        63
    wisetc  
    OP
       May 31, 2019
    因为有时候金额既有用户输入又有后台代入,并不十分确定金额的来向是用户输入,用户输入的情形用来显示显然不需要做放大,然后混合系统来的数据就可能会出现问题,而且金额放大 1000 倍直观上感受并不能判断是放大后的结果(例如 1000,看不出是 1 元还是 1000 元),出现不确定性。于是,前端提倡,在前端运行中的过程量都是直接的真实数据,不希望做任何的特殊处理,对请求的后台接口封装做请求参数和返回数据的处理,但是有时候涉及到遍历,和特殊处理,这又是常见的一般性问题了,金额的字段名也不固定而且有时不必需,这显然却是一种运算力的浪费。
    tailf
        64
    tailf  
       May 31, 2019
    用 decimal,没有对账风险
    allanzhuo
        65
    allanzhuo  
       May 31, 2019
    我司有个十几年的所谓架构师也是这样设计的,最后他滚蛋了,哈哈哈
    wlfeng
        66
    wlfeng  
       May 31, 2019
    和钱有关的数据老老实实用 decimal,不要搞事情,不然出问题了你哭都来不及
    wupher
        67
    wupher  
       May 31, 2019
    可以

    如果计算量很多很大,使用 long 会比使用 Big Decimal 效率高很多。更别提 Big Decimal 的进位策略。

    但是,使用 long 也要评估是否会碰到溢出。尤其是大规模统计的情况下。
    CantSee
        68
    CantSee  
       May 31, 2019
    decimal 啊,这玩意跟数据库同步,多方便
    jzmws
        69
    jzmws  
       May 31, 2019
    我第一反应为什么不用 decimal 货币型 ,最不济的用 bigint 按分来存
    SayNight
        70
    SayNight  
       May 31, 2019   ❤️ 1
    如果业务场景金额只有加减,且判断以后绝对不会有复杂运算,因为是扩大倍数存储,要考虑 long 型溢出问题。

    建议 BigDecimal,前面有 V 友提到银行用的是这个。曾在支付公司待过几年,每天流水十来亿,只允许使用:BigDecimal。不然很容易搞出事。
    sivacohan
        71
    sivacohan  
    PRO
       May 31, 2019
    看你常见,如果是简单的购买行为,那你的方法是可以的。
    如果是金融系统,一般做法是 Decimal 保留 4 到 6 位小数,然后定期核查,检查因为精度问题造成的损失。
    最常见的常见就是 100 块钱三个人平分,最后总会有一个人多分到一分钱。
    jzmws
        72
    jzmws  
       May 31, 2019
    @keepeye 最好做个四舍六入的 要不然到最后帐不平 .
    yalin
        73
    yalin  
       May 31, 2019
    听说平安一钱包大佬用这个库: https://github.com/JodaOrg/joda-money
    msg7086
        74
    msg7086  
       May 31, 2019
    如果你是无关紧要的金融服务,比如开 VPS 收个钱什么的,那存个千分之一元也就算了。
    如果是以金融为核心的服务,当然直接开大数运算咯,Decimal 或者金融专用小数格式直接用就是了。
    fairyto2
        75
    fairyto2  
       May 31, 2019
    @22too 而且也只能从 String 初始化
    thet
        76
    thet  
       May 31, 2019 via Android
    我是直接用的 decimal
    lzj307077687
        77
    lzj307077687  
       May 31, 2019
    反正我认为我的项目 decimal 是够用的
    north521
        78
    north521  
       May 31, 2019
    @9151 还有可能 p2p
    ZiLong
        79
    ZiLong  
       May 31, 2019
    Bigdecimal 挺好,就是那个效率是真真的慢
    VANHOR
        80
    VANHOR  
       May 31, 2019
    用整型,存分就可以。
    shuqin2333
        81
    shuqin2333  
       May 31, 2019
    我们公司使用的 long,mysql 数据类型用的 bigint。前台存取的时候自行*/10000
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2492 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 180ms · UTC 00:51 · PVG 08:51 · LAX 17:51 · JFK 20:51
    ♥ Do have faith in what you're doing.