Android (big) fail on float values product

2020-08-04 10:38发布

the situation is drammatic... It's 5 days that i must resolve this problem and i can't get out.

The problem: a simple operation as a product make always wrong result. Why?

Extract of the code:

//all vars are float
// resultVec is a vector [3]
// Rs is a vector [3]
// accelerationvalues is a vector [3]
   resultVec[0]=Rs[0]*accelerationvalues[0]+Rs[1]*accelerationvalues[1]+Rs[2]*accelerationvalues[2];

//debug to print result

Log.d("e", "("+Rs[0]+")*("+accelerationvalues[0]+")+("+Rs[1]+")*("+accelerationvalues[1]+")+("+Rs[2]+")*("+accelerationvalues[2]+")="+(resultVec[0]));

And this is the Log Cat result: enter image description here But you can simply try that this is wrong: search on google

(0.040147018)*(-0.9942854)+(0.9984244)*(-0.32688835)+(0.039202508)*(9.343558)

And you'll find that the true result is 8.67678679 × 10-9 that is very different from the other..This error is repeated always i execute the programm, some time the difference is in the sign too!

What is the problem?

I've tried all the way to solve it! (some are posted below):

You can find the full source here.

  1. save Rs and accelerationvalues in an arraylist and perform calculation outside the listner. No result.
  2. Convert float to double, no result.
  3. Many others ways

P.S. This problem occour only for resultVec[0] and resultVec[1], instead resultVec[2] is well calculated.

4条回答
一纸荒年 Trace。
2楼-- · 2020-08-04 10:48

you're multiplying floating point numbers, accumulating rounding errors all the way down. Using double-precision won't solve the underlying issue, which is that binary computers cannot accurately represent decimal floating point numbers.

Read this: http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html for an overview of the problem.

You'll likely find you need to perform the calculations using the BigDecimal class.

查看更多
乱世女痞
3楼-- · 2020-08-04 10:57

This is not android's fault, it is how you designed the app.

Execute this in a plain Java application:

public class ArithmTest {

    public static void main(String[] args) {
        double d1 = (0.040147018)*(-0.9942854)+(0.9984244)*(-0.32688835)+(0.039202508)*(9.343558);
        System.out.println(d1);

        float f1 = 0.040147018f;
        float f2 = -0.9942854f;

        float f3 = 0.9984244f;
        float f4 = -0.32688835f;

        float f5 = 0.039202508f;
        float f6 = 9.343558f;

        System.out.println(f1*f2 + f3*f4 + f5*f6);

    }
}

As you can see, the first one is the same as Google's, and the second printout is your app's value. To solve this, I think you should use double instead of float in every variable you declared, e.g.: accelerationvalues and resultVec.

查看更多
一纸荒年 Trace。
4楼-- · 2020-08-04 11:01

I think that you should to use double type instead of float

查看更多
贪生不怕死
5楼-- · 2020-08-04 11:05

You might be running into the limited precision of floating point values. In order to confirm this you can change the float into double or use BigDecimal.

查看更多
登录 后发表回答