看 Android SDK 的 TypedValue#applyDimension 有感。 贴代码:
public static float applyDimension(int unit, float value,
DisplayMetrics metrics)
{
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}
1
weeei 2022-11-08 10:39:09 +08:00
没有区别,这作者写的字面量都不统一。
效果是一样的,个人代码风格而已 最后 return 0 ,而不是 return 0.0f 就写的很随意。 |
2
fds 2022-11-08 10:45:05 +08:00 2
谷歌一下呗。除法比乘法慢。代码中这里的可以确定结果的除法在编译时就算出来了,所以运行时就只用乘法,不会影响速度。
https://stackoverflow.com/a/4125074/502851 |
3
Maboroshii 2022-11-08 10:47:29 +08:00
可能更想表达 72 分之 1 ?
|
5
mxT52CRuqR6o5 2022-11-08 11:05:13 +08:00
@ysc3839 c 的话肯定能靠编译器优化好不需要写的这么拐弯抹角,java 我就不清楚了
|
8
maggch97 2022-11-08 11:12:31 +08:00 2
@mxT52CRuqR6o5 GCC 要做这个优化也是需要开 -ffast-math 的,而且一般是不会开这个编译选项的
|
9
ysc3839 2022-11-08 11:15:32 +08:00
@mxT52CRuqR6o5 Java 应该也有优化的,之前在网上听说 Java 等带虚拟机的运行时,长时间运行性能是能超越 C++ 这种编译好的程序的,因为虚拟机能在运行时统计性能数据并优化代码。
@maggch97 这个解释是最合理的。 |
10
shijingshijing 2022-11-08 11:16:15 +08:00
@dcsuibian 错了,直接做除法比乘以倒数慢多了,如果我记得没错的话,除法是用无限逼近的方法实现的,而乘法有硬件直接支持,现在的 CPU 和 GPU ,内部都有 MAD 或者 FMAD 指令,能够在很短时间直接出结果。而求倒也有快速实现的方法。所以综合起来先求倒再做乘法比直接除要快很多。
https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation |
12
star9029 2022-11-08 11:26:36 +08:00
clang -O1
float test(float x) { return x / 2; } 优化成 x * 0.5 这种优化在 native 语言都是基操,java 就不清楚了 |
13
maggch97 2022-11-08 11:43:45 +08:00 1
@star9029 /2 跟 /72 是两个问题,https://godbolt.org/ 在这上面玩一下看看吧
|
14
maggch97 2022-11-08 11:45:44 +08:00
编译器开到 -O1000 都不会把 /72 优化成 *1/72
|
16
ho121 2022-11-08 11:54:24 +08:00
```
>>> 111 / 72 1.5416666666666667 >>> 111 * (1/72) 1.5416666666666665 >>> ``` 编译器不可能默认做这种优化 |
17
icyalala 2022-11-08 14:15:32 +08:00
https://godbolt.org/z/jWxqEGT9q
一个是 fmul ,一个是 fdiv ,不是等同的,编译不能优化 |
18
xz410236056 2022-11-08 14:29:50 +08:00 1
|
19
shijingshijing 2022-11-08 14:51:46 +08:00
@xz410236056 这个除法我记得是用 MicroCode 实现的,而 FMAD 是纯硬件电路。这篇文章里面讨论了这个问题:
https://stackoverflow.com/questions/40354978/why-does-c-code-for-testing-the-collatz-conjecture-run-faster-than-hand-writte/ 里面有人给出了数据: 乘法: Also mul rbx on the OP's Haswell CPU is 2 uops with 3c latency (and 1 per clock throughput). imul rcx, rbx, 3 is only 1 uop, with the same 3c latency. Two ADD instructions would be 2 uops with 2c latency. 除法: e.g. on the OP's Haswell CPU: DIVSD is 1 uop, 10-20 cycles latency, one per 8-14c throughput. div r64 is 36 uops, 32-96c latency, and one per 21-74c throughput. Skylake has even faster FP division throughput (pipelined at one per 4c with not much better latency), but not much faster integer div. 新的 x86 和 x64 的指令集和架构设计有很多优化和变更,我也没有怎么关注这方面最新的动态,但基本上都默认了除法比乘法慢很多。 |
20
tool2d 2022-11-08 15:00:31 +08:00
SSE2 加法:451 K 指令 /s
SSE2 减法:451 K 指令 /s SSE2 乘法:452 K 指令 /s SSE2 除法:118 K 指令 /s 除法是所有数学运算里最慢的。反而是现代 CPU 把乘法优化到和加法一样快,这是我没想到的。 |
21
xz410236056 2022-11-08 15:58:05 +08:00
@shijingshijing #19 确实,刚刚看了一下 https://uops.info/table.html 吞吐量和延迟仍然有差距。
|