金额的存储用 long 可以吗 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wisetc
V2EX    数据库

金额的存储用 long 可以吗

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

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

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

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

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

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

    建议 BigDecimal,前面有 V 友提到银行用的是这个。曾在支付公司待过几年,每天流水十来亿,只允许使用:BigDecimal。不然很容易搞出事。
    sivacohan
        71
    sivacohan  
    PRO
       2019-05-31 11:08:34 +08:00
    看你常见,如果是简单的购买行为,那你的方法是可以的。
    如果是金融系统,一般做法是 Decimal 保留 4 到 6 位小数,然后定期核查,检查因为精度问题造成的损失。
    最常见的常见就是 100 块钱三个人平分,最后总会有一个人多分到一分钱。
    jzmws
        72
    jzmws  
       2019-05-31 11:08:53 +08:00
    @keepeye 最好做个四舍六入的 要不然到最后帐不平 .
    yalin
        73
    yalin  
       2019-05-31 11:11:52 +08:00
    听说平安一钱包大佬用这个库: https://github.com/JodaOrg/joda-money
    msg7086
        74
    msg7086  
       2019-05-31 12:00:20 +08:00
    如果你是无关紧要的金融服务,比如开 VPS 收个钱什么的,那存个千分之一元也就算了。
    如果是以金融为核心的服务,当然直接开大数运算咯,Decimal 或者金融专用小数格式直接用就是了。
    fairyto2
        75
    fairyto2  
       2019-05-31 12:20:00 +08:00
    @22too 而且也只能从 String 初始化
    thet
        76
    thet  
       2019-05-31 12:58:39 +08:00 via Android
    我是直接用的decimal
    lzj307077687
        77
    lzj307077687  
       2019-05-31 13:41:20 +08:00
    反正我认为我的项目 decimal 是够用的
    north521
        78
    north521  
       2019-05-31 13:58:16 +08:00
    @9151 还有可能 p2p
    ZiLong
        79
    ZiLong  
       2019-05-31 14:04:57 +08:00
    Bigdecimal 挺好,就是那个效率是真真的慢
    VANHOR
        80
    VANHOR  
       2019-05-31 14:07:01 +08:00
    用整型,存分就可以。
    shuqin2333
        81
    shuqin2333  
       2019-05-31 14:17:20 +08:00
    我们公司使用的 long,mysql 数据类型用的 bigint。前台存取的时候自行*/10000
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3208 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 11:29 PVG 19:29 LAX 04:29 JFK 07:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86