Android (большой) терпит неудачу на продукте с плавающей запятой - PullRequest
0 голосов
/ 07 ноября 2011

ситуация драматическая ... Мне нужно решить эту проблему в течение 5 дней, и я не могу выбраться.

Проблема: простая операция как продукт всегда приводит к неправильному результату. Почему?

Выписка из кода:

//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]));

И вот результат Log Cat: enter image description here Но вы можете просто попробовать, что это не так: поиск в Google

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

И вы обнаружите, что истинный результат - 8.67678679 × 10-9 , который сильно отличается от другого. Эта ошибка повторяется всегда, когда я выполняю программу, в некотором случае разница тоже в знаке!

В чем проблема?

Я пытался все это решить! (некоторые опубликованы ниже):

Вы можете найти полный источник здесь.

  1. сохранить Rs и значения ускорения в массиве и выполнить расчет вне списка. Нет результата.
  2. Преобразовать число с плавающей точкой в ​​двойное, без результата.
  3. Многие другие способы

P.S. Эта проблема возникает только для resultVec[0] и resultVec[1], вместо этого resultVec[2] хорошо рассчитано.

Ответы [ 4 ]

2 голосов
/ 07 ноября 2011

Вы умножаете числа с плавающей запятой, накапливая ошибки округления до конца. Использование двойной точности не решит основную проблему, заключающуюся в том, что двоичные компьютеры не могут точно представлять десятичные числа с плавающей запятой.

Прочитайте это: http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html для обзора проблемы.

Скорее всего, вам понадобится выполнить вычисления с использованием класса BigDecimal.

1 голос
/ 07 ноября 2011

Это не вина андроида, это то, как вы разработали приложение.

Выполните это в простом Java-приложении:

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);

    }
}

Как видите, первая такая же, как у Google, а вторая распечатка - это ценность вашего приложения. Чтобы решить эту проблему, я думаю, вы должны использовать double вместо float в каждой объявленной вами переменной, например: accelerationvalues и resultVec.

0 голосов
/ 07 ноября 2011

Возможно, вы столкнулись с ограниченной точностью значений с плавающей запятой.Чтобы подтвердить это, вы можете изменить float на double или использовать BigDecimal.

0 голосов
/ 07 ноября 2011

Я думаю, что вы должны использовать двойной тип вместо float

...