当前位置: 首页 > 知识库问答 >
问题:

为什么Java的math.min在我的Android应用程序中这么慢?

阳光辉
2023-03-14

我对一些代码进行了分析,并对math.min(float,float)花费了这么多时间感到惊讶。

private static float min2(float v1, float v2, float v3) {
    return Math.min(Math.min(v1,v2),v3);
}

但我发现这快了大约5倍:

private static float min1(float v1, float v2, float v3) {
    if (v1 < v2 && v1 < v3) {
        return v1;
    }
    else if (v2 < v3) {
        return v2;
    }
    else {
        return v3;
    }
}

下面是Math.min的代码以供参考:

public static float min(float f1, float f2) {
    if (f1 > f2) {
        return f2;
    }
    if (f1 < f2) {
        return f1;
    }
    /* if either arg is NaN, return NaN */
    if (f1 != f2) {
        return Float.NaN;
    }
    /* min(+0.0,-0.0) == -0.0 */
    /* 0x80000000 == Float.floatToRawIntBits(-0.0f) */
    if (Float.floatToRawIntBits(f1) == 0x80000000) {
        return -0.0f;
    }
    return f2;
}

注意:我的用例是对称的,上面的情况都适用于max,而不是min。

我在我的应用程序中添加了以下代码,以尝试获得更好的数据:

long min1Times = 0L;
long min2Times = 0L;
...
// loop assigning touch values to v1, v2, v3
        long start1 = System.nanoTime();
        float min1 = min1(v1, v2, v3);
        long end1 = System.nanoTime();
        min1Times += end1 - start1;
        long start2 = System.nanoTime();
        float min2 = min2(v1, v2, v3);
        long end2 = System.nanoTime();
        min2Times += end2 - start2;
        double ratio = (double) (min1Times) / (double) (min2Times);
        Log.d("", "ratio: " + ratio);

这将打印每个新触摸事件的运行比率。当我在屏幕上旋转手指时,首先记录的比率是0.0infinitynan。这让我觉得这个测试不是很准确地测量时间。随着收集到更多的数据,比率往往在.851.15之间变化。

共有1个答案

冷夜洛
2023-03-14

问题是关于浮点值的精度。

如果使用参数(0.0f,-0.0f,0.0f)调用方法,它将返回0.0f作为最小的浮点数-它不是(浮点数方面,-0.0f更小)

嵌套的Min-Method将返回预期的结果。

Java将0.0f==-0.0f处理为true,但是:new Float(0.0)).equals(new Float(-0.0))将为falsemath.min将考虑这一点,而您的方法不考虑。

使用浮点值时,不应使用较小或等于的运算符。相反,您应该根据预选的delta比较数字,以考虑它们更小、更大或相等。

float delta = 0.005
if (Math.abs(f1 - f2) < delta) //Consider them equal.
if (Math.abs(f1 - f2) > delta) // not equal. 

这就是math.min方法末尾所发生的事情--通过实际检查一个数字是否为-0.0f,以一种非常非常精确的方式--按位。

所以性能上的缺点就是计算的结果更准确。

但是,如果比较“10”、“5”和“8”这样的浮点值,就不会有性能差异,因为0检查永远不会命中。

 类似资料:
  • 我查看了源代码中的一些内容,并注意到虽然(或其长的对应部分)是这样实现的: 这对我来说是完全有意义的,这和我想做的是一样的。但是,double/float的实现是这样的: 我完全傻眼了。是否将与其自身进行比较?第二张支票是为了什么?为什么它的实现方式不像int/long版本一样?

  • 我试图隐藏Actionbar并改用工具栏,但如果我更改Theme.appcompat.light.NoActionBar,它确实会隐藏,但应用程序在行setContentView(r.layout.activity_main)处崩溃; 尽管它确实使用getSupportActionBar()隐藏。hide();但我不能用这个代码 Toolbar Toolbar=(Toolbar)findViewB

  • 问题内容: 在我的Java应用程序中,我有此代码 当我为 android 2.3(第10级) 构建它时, 它可以编译并正常工作。但是,当我为 android 4.0(级别15) 构建它时,它会编译并在运行时崩溃并出现以下错误 当我评论这条线,并建立它工作正常,没有问题.. 所以我不明白为什么会这样,这段代码意味着什么? 问题答案: @Override public void onAttachedT

  • 另外,为什么在键入Style标记的name属性时执行Ctrl+Space操作时看不到所有的r.attr元素? 请帮忙。谢了。

  • 每当我请求权限时,我的应用程序就会崩溃。作为清单标记的子项,我在清单中定义了正确的使用权限。它没有给出任何错误,只是一个弹出窗口说包安装程序已经停止,监视器中有一行说“sendUserActionEvent()mView==null”,我不确定这与崩溃有关。 这是我请求权限的片段: 最低sdk设置为23,在三星Galaxy S7上进行测试。 你可以在这里看到完整的代码https://github.