浮点问题 [英] floating point issue

查看:111
本文介绍了浮点问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从UI进入的浮动值为0.1。



但是,当将该字符串转换为float时,我得到0.10 ... 01。问题是附加非零数字。



感谢,



iSight

解决方案

我见过的最好的网站解释了为什么一些数字无法准确表示 Harald Schmidt的IEEE754转换器网站

这是一个在线工具,用于显示IEEE754单精确值,我喜欢这么多,我写了我自己的Java应用程序来做它(和双精度以及)。



底线,只有大约40亿不同的32位值,但是在任何两个不同的值之间存在无限数量的实数值。所以你有一个精度问题。



如果你想要更多的精度和/或更好的类型为十进制值,你可以:

$ b
  • 使用小数类型

  • 使用大数字库,如 GMP (虽然我拒绝在生产代码中使用它,因为我发现它不处理内存不足优雅)。



  • 或者,您可以使用不准确的值(它们的错误率非常低,百万从浮动,从内存),只是打印出来的精度较低。将 0.10000000145 打印到两位小数,即可得到 0.10



    你必须做数百万和数百万的添加,使错误显着累积。当然还有很多其他操作。






    对于为什么得到该值, 0.1 存储在IEEE754单精度格式中,如下(符号,指数和尾数):

      s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm 1 / n 
    0 01111011 10011001100110011001101
    |||||||||||||||||||||| + 8388608
    |||||||||||||||||||||||||| + - 4194304
    ||||||||||||||| |||| + --- 2097152
    ||||||||||||||||||| + ---- 1048576
    |||||||| |||||||||| + ----- 524288
    |||||||||||||||| + ------ 262144
    |||||||||||||||| + ------- 131072
    ||||||||||||||| + ----- --- 65536
    |||||||||||||| + --------- 32768
    ||||||||||||| + ---------- 16384
    |||||||||||| + ----------- 8192
    ||||| |||||| + ------------ 4096
    |||||||||| + ------------- 2048
    ||||||||| + -------------- 1024
    |||||||| + --------- ------ 512
    ||||||| + ---------------- 256
    |||||| + --- -------------- 128
    ||||| + ------------------ 64
    || || + ------------------- 32
    ||| + ------------------- - 16
    || + --------------------- 8
    | + ------------- --------- 4
    + ----------------------- 2



    符号是正的,很容易。



    指数 64 + 32 + 16 + 8 + 2 + 1 = 123-127 bias = -4 ,因此乘数为2 -4 1 / 16



    尾数是大块的。它由 1 (隐式基数)加(每个值都等于1 /(2 n ))的所有位组成 n 1 开始并向右增加), {1/2,1/16,1 / 32,1 / 256,6 / 512,1 / 4096,1 / 8192,1 / 65536,1 / 131072,1 / 1048576,1 / 2097152,1 / 8388608}



    当你添加所有这些,你会得到 1.60000002384185791015625



    当乘以乘数时,得到 0.100000001490116119384765625 ,与Harald网站上的双精度值匹配,直到它被打印:

      0.10000000149011612(out by 0.00000000149011612)

    你关闭最低有效位(最右边的位),这是你可以做的最小的向下运动,你得到:

      0.09999999403953552 out by 0.00000000596046448)

    将这两个组合在一起:

      0.10000000149011612(out by 0.00000000149011612)
    |
    0.09999999403953552(out by 0.00000000596046448)

    您可以看到第一个是更接近的匹配,大约四分之一(14.9:59.6)。这是您可以得到的最接近的价值 0.1


    I have a floating value as 0.1 entering from UI.

    But, while converting that string to float i am getting as 0.10...01. The problem is the appending of non zero digit. How do i tackle with this problem.

    Thanks,

    iSight

    解决方案

    The best site I've ever seen that explains why some numbers can't be represented exactly is Harald Schmidt's IEEE754 Converter site.

    It's an online tool for showing representations of IEEE754 single precision values and I liked it so much, I wrote my own Java app to do it (and double precision as well).

    Bottom line, there are only about four billion different 32-bit values you can have but there are an infinite number of real values between any two different values. So you have a problem with precision. That's something you'll have to get used to.

    If you want more precision and/or better type for decimal values, you can either:

    • switch to a higher number of bits.
    • use a decimal type
    • use a big-number library like GMP (although I refuse to use this in production code since I discovered it doesn't handle memory shortages elegantly).

    Alternatively, you can use the inaccurate values (their error rates are very low, something like one part per hundred million for floats, from memory) and just print them out with less precision. Printing out 0.10000000145 to two decimal places will get you 0.10.

    You would have to do millions and millions of additions for the error to accumulate noticeably. Less of other operations of course but still a lot.


    As to why you're getting that value, 0.1 is stored in IEEE754 single precision format as follows (sign, exponent and mantissa):

    s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm    1/n
    0 01111011 10011001100110011001101
               ||||||||||||||||||||||+- 8388608
               |||||||||||||||||||||+-- 4194304
               ||||||||||||||||||||+--- 2097152
               |||||||||||||||||||+---- 1048576
               ||||||||||||||||||+-----  524288
               |||||||||||||||||+------  262144
               ||||||||||||||||+-------  131072
               |||||||||||||||+--------   65536
               ||||||||||||||+---------   32768
               |||||||||||||+----------   16384
               ||||||||||||+-----------    8192
               |||||||||||+------------    4096
               ||||||||||+-------------    2048
               |||||||||+--------------    1024
               ||||||||+---------------     512
               |||||||+----------------     256
               ||||||+-----------------     128
               |||||+------------------      64
               ||||+-------------------      32
               |||+--------------------      16
               ||+---------------------       8
               |+----------------------       4
               +-----------------------       2
    

    The sign is positive, that's pretty easy.

    The exponent is 64+32+16+8+2+1 = 123 - 127 bias = -4, so the multiplier is 2-4 or 1/16.

    The mantissa is chunky. It consists of 1 (the implicit base) plus (for all those bits with each being worth 1/(2n) as n starts at 1 and increases to the right), {1/2, 1/16, 1/32, 1/256, 1/512, 1/4096, 1/8192, 1/65536, 1/131072, 1/1048576, 1/2097152, 1/8388608}.

    When you add all these up, you get 1.60000002384185791015625.

    When you multiply that by the multiplier, you get 0.100000001490116119384765625, matching the double precision value on Harald's site as far as it's printed:

    0.10000000149011612 (out by 0.00000000149011612)
    

    And when you turn off the least significant (rightmost) bit, which is the smallest downward movement you can make, you get:

    0.09999999403953552 (out by 0.00000000596046448)
    

    Putting those two together:

    0.10000000149011612 (out by 0.00000000149011612)
                                          |
    0.09999999403953552 (out by 0.00000000596046448)
    

    you can see that the first one is a closer match, by about a factor of four (14.9:59.6). So that's the closest value you can get to 0.1.

    这篇关于浮点问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆