Java Android(大)浮点值失败产品

Java Android(大)浮点值失败产品,java,android,math,floating-point,android-sensors,Java,Android,Math,Floating Point,Android Sensors,形势严峻。。。这五天我必须解决这个问题,我不能出去 问题是:作为一个产品,简单的操作总是会产生错误的结果。为什么? 代码摘录: //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

形势严峻。。。这五天我必须解决这个问题,我不能出去

问题是:作为一个产品,简单的操作总是会产生错误的结果。为什么?

代码摘录:

//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]));
这是对数Cat结果: 但你可以试着证明这是错误的:在谷歌上搜索

(0.040147018)*(-0.9942854)+(0.9984244)*(-0.32688835)+(0.039202508)*(9.343558)
你会发现真正的结果是8.67678679×10-9,这与另一个非常不同..这个错误总是重复,我执行程序,有时差异也在符号中

有什么问题

我已经想尽办法解决了!(有些贴在下面):

  • 将Rs和AccelerationValue保存在arraylist中,并在listner之外执行计算。没有结果
  • 将float转换为double,没有结果
  • 许多其他方式

  • 注意:此问题仅适用于
    resultVec[0]
    resultVec[1]
    ,而不是
    resultVec[2]
    计算得很好。

    我认为您应该使用双精度而不是浮点值

    我认为您应该使用双精度而不是浮点值

    您可能会遇到浮点值精度有限的问题。为了确认这一点,您可以将
    浮点
    更改为
    双精度
    ,或者使用
    大十进制

    ,您可能会遇到浮点值的有限精度。为了确认这一点,您可以将
    浮点
    更改为
    双精度
    ,或者使用
    大十进制

    将浮点数相乘,一路累积舍入误差。使用双精度无法解决根本问题,即二进制计算机无法准确表示十进制浮点数

    阅读以下内容:了解问题的概述


    您可能会发现需要使用BigDecimal类执行计算。

    您将浮点数相乘,一路累积舍入误差。使用双精度无法解决根本问题,即二进制计算机无法准确表示十进制浮点数

    阅读以下内容:了解问题的概述


    您可能会发现需要使用BigDecimal类执行计算。

    这不是android的错,这是您设计应用程序的方式

    在普通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);
    
        }
    }
    
    正如你所看到的,第一个和谷歌的一样,第二个打印输出是你的应用程序的值。
    为了解决这个问题,我认为你应该在你声明的每个变量中使用double而不是float,例如:
    accelerationvalues
    resultVec

    这不是android的错,这是你设计应用程序的方式

    在普通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);
    
        }
    }
    
    正如你所看到的,第一个和谷歌的一样,第二个打印输出是你的应用程序的值。
    为了解决这个问题,我认为您应该在声明的每个变量中使用double而不是float,例如:
    accelerationvalues
    resultVec

    您对二进制浮点了解多少?特别是,如果您使用的是
    float
    ,那么您是否知道只有7位有效数字的精度?您是如何将float转换为double的?告诉我:为什么错误只出现在
    resultVec[0]
    resultVec[1]
    中,而从来没有出现在
    resultVec[2]中
    ?@Lork:你不能简单地查看两个浮点结果(例如,日志中的一个和谷歌的一个?),然后判断“他们错了”。这根本不是对浮点结果的比较。你需要用ε来比较它们。当考虑到误差传播和使用正确的ε时,您可能会发现这两个结果实际上是相同的。(我并不是说他们在这种情况下是正确的,但你的方法肯定是错误的)我非常确定真实结果是8.676786 80 E-9。但是这么小的错误可能不会有什么不同。你对二进制浮点有多了解?特别是,如果您使用的是
    float
    ,那么您是否知道只有7位有效数字的精度?您是如何将float转换为double的?告诉我:为什么错误只出现在
    resultVec[0]
    resultVec[1]
    中,而从来没有出现在
    resultVec[2]中
    ?@Lork:你不能简单地查看两个浮点结果(例如,日志中的一个和谷歌的一个?),然后判断“他们错了”。这根本不是对浮点结果的比较。你需要用ε来比较它们。当考虑到误差传播和使用正确的ε时,您可能会发现这两个结果实际上是相同的。(我并不是说他们在这种情况下是正确的,但你的方法肯定是错误的)我非常确定真实结果是8.676786 80 E-9。但是这么小的错误可能不会有什么不同。这里有一个很好的链接:戈德堡的论文是我最喜欢的;)但是我不同意他应该使用BigDecimal类来执行计算。人们一直在编写(并一直在编写)游戏(在旧机器和移动设备上),要么使用浮点/双精度计算并正确跟踪错误传播,要么使用“整数数学”。创建大量BigDecimal对象(每秒60次,屏幕上数百个小对象,乘以所需的所有计算量)肯定会扼杀应用程序的性能。大家都同意,BigDecimal是在用锤子压扁蜗牛,但没有任何关于OP正在做什么以及他对FP的明显不熟悉的背景,这可能是最好的选择。另一方面,我认为所有的新程序员都应该抓住脖子上的赘肉,让他们阅读上面的文章:-)这里有一个很好的链接:戈德伯格的文章是我最喜欢的;)但是我不同意他应该使用BigDecim来进行计算