在进行算术运算(+-*/%)时,double和float哪个更快?考虑到内存原因,只使用float值是否值得?精度不是很重要。
如果我为使用的float数量越来越多而担心,可以随意称我为疯子。编辑1:这个问题之所以涉及到Android,是因为我认为内存很重要;如果是桌面开发,我甚至都不会问这个问题。
在进行算术运算(+-*/%)时,double和float哪个更快?考虑到内存原因,只使用float值是否值得?精度不是很重要。
如果我为使用的float数量越来越多而担心,可以随意称我为疯子。编辑1:这个问题之所以涉及到Android,是因为我认为内存很重要;如果是桌面开发,我甚至都不会问这个问题。
现在的CPU处理速度,在这两种类型的数据上应该大致相同。
"使用任何需要的精度以获得可接受的结果。"
这里在SO上已经有几次相关的提问了,这是其中的一篇。
编辑:
就速度而言,在较新的硬件上,浮点数和双精度没有区别。
请查看developer.android.com上的这篇文章。
由于Dalvik从Froyo(API 8及更高版本)开始进行JIT(即时编译)优化,因此ADT v21提示建议使用Double而不是Float。
我曾经使用FloatMath.sin,但它建议我改用Math.sin,并在“解释问题”上下文菜单中提供以下内容。听起来像是关于double与float而不仅仅是三角函数相关的一般性消息。
"在旧版Android中,由于性能原因,建议使用android.util.FloatMath操作float。然而,在现代硬件上,double与float一样快(虽然它们占用更多内存),并且在最近的Android版本中,由于JIT对java.lang.Math的优化方式,FloatMath实际上比使用java.lang.Math更慢。因此,如果您只针对Froyo及以上版本,请使用Math而不是FloatMath。"
希望这可以帮助你。
我不建议使用快速操作,但我相信对于浮点数的操作会更快,因为它们是32位的,而双精度浮点数则为64位。
http://developer.android.com/training/articles/perf-tips.html#AvoidFloat
避免使用浮点数
在 Android 设备上,使用浮点数通常比整数慢约 2 倍。
在速度方面,现代硬件上的 float 和 double 没有区别。而在空间方面,double 大约是 float 的两倍大小。就像桌面机一样,如果空间不是问题,您应该优先选择 double 而不是 float。
除此之外,即使对于整数,一些处理器拥有乘法硬件但缺少除法硬件。在这种情况下,整数除法和取模操作将在软件中执行。如果您正在设计哈希表或进行大量数学运算,需要考虑这一点。
浮点数是32位或4字节。
双精度浮点数是64位或8字节。
所以,是的,根据Sun Java认证书,浮点数的大小只有一半。
JIT或VM:它们将把数学运算转换为主机的本地指令集,这种转换对性能有很大影响。由于底层硬件在不同平台上可能差别很大,编写一个能够在所有情况下发出最佳代码的VM或JIT可能非常困难。最好还是使用JIT/VM推荐的快速类型(在本例中为整数),因为随着JIT和VM发出更有效的本地指令的能力越来越强,您的高级代码应该获得相关的性能提升而无需任何修改。
本地硬件(为什么第一级不完美):现今大多数处理器都有硬件浮点单元(支持浮点数和双精度浮点数)。如果存在这样的硬件单元,则浮点数/双精度浮点数可以比整数更快,除非还具有硬件整数支持。问题的复杂化在于,大多数CPU都有某种形式的SIMD(单指令多数据)支持,如果数据类型足够小,则允许操作向量化(例如,通过将两个浮点数放入每个寄存器中,在一个指令中添加4个浮点数,而不必为每个4倍精度浮点数使用一个完整寄存器)。这可以使使用更少位数的数据类型比双精度浮点数快得多,但牺牲了精度。
即使在桌面上,这也不是一个糟糕的问题。是的,今天它们非常快,但如果您正在实现复杂的算法(例如快速傅里叶变换),即使进行小的优化也会对算法的运行时间产生巨大影响。无论如何,回答您的问题“哪个更快:浮点数还是双精度”,答案是“取决于” :)
我也对此感到好奇,于是写了一个小测试:
#include <iostream>
#include <chrono>
template<typename numType>
void test(void) {
std::cout<< "Size of variable: " << sizeof(numType) << std::endl;
numType array[20000];
auto t1 = std::chrono::high_resolution_clock::now();
// fill array
for( numType& number : array ) {
number = 1.0014535;
}
auto t2 = std::chrono::high_resolution_clock::now();
// multiply each number with itself 10.000 times
for( numType& number : array ) {
for( int i=0; i < 10000 ; i++ ) {
number *= number;
}
}
auto t3 = std::chrono::high_resolution_clock::now();
auto filltime = t2 - t1;
auto calctime = t3 - t2;
std::cout<< "Fill time: " << filltime.count() << std::endl;
std::cout<< "Calc time: " << calctime.count() << std::endl;
}
int main(int argc, char* argv[]) {
test<float>();
test<double>();
}
我在Ubuntu 12.04 x64下使用GCC编译并运行它,处理器为Intel i7 3930k。
以下是结果:
Size of variable: 4
Fill time: 69
Calc time: 694303
Size of variable: 8
Fill time: 76
Calc time: 693363
结果是可重复的。因此,对于双精度浮点数的内存分配需要稍微更长一些时间,但实际计算时间完全相同。
出于好奇,我还在Windows 7 x64下使用Visual Studio 2012以发布模式编译了它,在intel i7 920处理器上运行。
(时间单位不同,因此请勿将上述结果与以下结果进行比较:仅适用于内部比较)
Size of variable: 4
Fill time: 0
Calc time: 3200183
Size of variable: 8
Fill time: 0
Calc time: 3890223
结果可以重复。
似乎在Windows上,分配是瞬时的,也许因为Linux实际上只有在使用内存时才给你,而Windows则立即将所有内存交给你,需要更少的系统调用。或者可能赋值被优化掉了。
双倍精度乘法比浮点数慢21.5%。这个与之前的测试的差异可能是由于不同的处理器(至少我最好的猜测是这样)。