想象一下,我有两个byte []数组,b1和b2,它们的字节对应两个双精度数。 一种选择就是......
double thisValue = readDouble(b1, s1);
double thatValue = readDouble(b2, s2);
return (thisValue < thatValue ? -1 : (thisValue == thatValue ? 0 : 1));
使用......
/** Parse an integer from a byte array. */
public static int readInt(byte[] bytes, int start) {
return (((bytes[start ] & 0xff) << 24) +
((bytes[start+1] & 0xff) << 16) +
((bytes[start+2] & 0xff) << 8) +
((bytes[start+3] & 0xff)));
}
/** Parse a long from a byte array. */
public static long readLong(byte[] bytes, int start) {
return ((long)(readInt(bytes, start)) << 32) +
(readInt(bytes, start+4) & 0xFFFFFFFFL);
}
/** Parse a double from a byte array. */
public static double readDouble(byte[] bytes, int start) {
return Double.longBitsToDouble(readLong(bytes, start));
}
(代码取自apache hadoop source here和here)。
问题是,你有他们的字节表示,所以看起来浪费实际上必须把它们变成双重,尽管这可能是如此大大优化,可以忽略不计。我确信Hadoop的人知道他们在做什么,我只是好奇为什么直接比较这些比特不会更好/更快?或者也许编译器足够智能,可以看到这种情况并做到这一点。
由于
答案 0 :(得分:1)
由于structure的IEEE floating-point format,您不能简单地检查所有位是否相同:例如,-0和+0具有不同的表示,但被认为是相等的;和具有许多不同表示的NaN值永远不会等于任何东西,包括具有相同表示的其他NaN值。
虽然你自己可以自己实现这些检查,但它很快变得非常复杂,并且不值得:你需要检查的“子值”没有自己的字节,所以你仍然必须提取字节并抛出它们变成更大的值 - 然后你必须实际检查所有不同的条件。
换句话说,你最终会做上述代码所做的事情,但是你需要花费更多的代码,并且你不太可能比已经存在的代码更好。< / p>
答案 1 :(得分:0)
一个字节数组可能包含标准化double值的位模式,另一个字节数组包含相同值的非标准化表示。在这种情况下,在比较字节值失败的情况下,转换和比较为double值将会成功。
答案 2 :(得分:0)
通过逐位比较比较浮点值存在很多问题 - 例如,一个数字可能是非正规数而另一个数字不是。它们可能是“相同的”或可比的,但它们的按位表示不会。
答案 3 :(得分:0)
我想说,你将获得“最有效”答案的唯一真正方法是进行15-20分钟的实验。老实说,我不知道使用详细的hadoop方法是否比将byte []加载到ByteArrayInputStream并使用DataInputStream装饰该流更快(或更多/更不准确)。 (DataInputStream有一个.getDouble()方法)
byte[] myData = ........
ByteArrayInputStream bais = ByteArrayInputStream(myData);
DataInputStream dis = DataInputStream(bais);
double d1 = dis.getDouble();
double d2 = dis.getDouble();
告诉我们你的基准是什么!