Algorithm 浮点数的二进制搜索/二分法
使用二进制搜索很容易找到整数:首先猜测数量级,然后继续划分区间。 描述如何查找任意有理数 设置好场景后,我的问题类似:我们如何猜测IEEE 754浮点数?假设不是NaN,但其他一切都是公平的。对于每一次猜测,您的程序都会被告知所讨论的数字是更高、相等还是更低。尽量减少最坏情况下所需的猜测次数 (这不是一个家庭作业。不过,如果这个问题有一个有趣的答案,我可能会做一个。这个答案不仅仅是“用大量的特殊情况处理将浮点数字困难打得死去活来。”)Algorithm 浮点数的二进制搜索/二分法,algorithm,floating-point,binary-search,numerics,Algorithm,Floating Point,Binary Search,Numerics,使用二进制搜索很容易找到整数:首先猜测数量级,然后继续划分区间。 描述如何查找任意有理数 设置好场景后,我的问题类似:我们如何猜测IEEE 754浮点数?假设不是NaN,但其他一切都是公平的。对于每一次猜测,您的程序都会被告知所讨论的数字是更高、相等还是更低。尽量减少最坏情况下所需的猜测次数 (这不是一个家庭作业。不过,如果这个问题有一个有趣的答案,我可能会做一个。这个答案不仅仅是“用大量的特殊情况处理将浮点数字困难打得死去活来。”) 编辑:如果我在搜索方面做得更好的话,我本来可以找到的---但
编辑:如果我在搜索方面做得更好的话,我本来可以找到的---但只有在你已经知道重新解释为
int
有效的情况下,这才有效(需要注意)。所以就不谈这个了。感谢哈罗德给了我一个很好的回答 同样的方法也适用于浮点数。更糟糕的情况是运行时间为O(logn)
同样的方法也适用于浮点数。更糟糕的情况是运行时间为O(logn)
IEEE-754 64位浮点数实际上是64位表示。此外,除了NaN值之外,浮点比较和正值整数比较之间没有区别。(也就是说,符号位未设置的两个位模式将产生相同的比较结果,无论您是将它们作为
int64\t
还是double
进行比较,除非其中一个位模式是浮点NaN-)
这意味着您可以通过一次猜测一位,在64次猜测中找到一个数字,即使该数字为±∞. 首先将数字与0进行比较;如果目标是“更少”,则按照如下相同的方式进行猜测,但在猜测之前先否定它们。(由于IEEE-754浮点数是符号/量级,您可以通过将符号位设置为1来对数字求反。或者您可以重新解释正位模式,然后用浮点对结果求反。)
然后,从最高阶值位开始,一次猜一位。如果数字大于或等于猜测值,则将该位设置为1;如果数字较小,则将该位设置为0;然后继续下一位,直到没有了。要构造猜测,请将位模式重新解释为double
有两个警告:
IEEE-754 64位浮点数实际上是64位表示。此外,除了NaN值之外,浮点比较和正值整数比较之间没有区别。(也就是说,符号位未设置的两个位模式将产生相同的比较结果,无论您是将它们作为
int64\t
还是double
进行比较,除非其中一个位模式是浮点NaN-)
这意味着您可以通过一次猜测一位,在64次猜测中找到一个数字,即使该数字为±∞. 首先将数字与0进行比较;如果目标是“更少”,则按照如下相同的方式进行猜测,但在猜测之前先否定它们。(由于IEEE-754浮点数是符号/量级,您可以通过将符号位设置为1来对数字求反。或者您可以重新解释正位模式,然后用浮点对结果求反。)
然后,从最高阶值位开始,一次猜一位。如果数字大于或等于猜测值,则将该位设置为1;如果数字较小,则将该位设置为0;然后继续下一位,直到没有了。要构造猜测,请将位模式重新解释为double
有两个警告:
public class GuessComparer
{
private float random;
public GuessComparer() // generate a random float and keep it private
{
Random rnd = new Random();
var buffer = new byte[4];
rnd.NextBytes(buffer);
random = BitConverter.ToSingle(buffer, 0);
}
public int CheckGuess(float quess) // answer whether number is high, lower or the same.
{
return random.CompareTo(quess);
}
}
public class FloatFinder
{
public static int Find(GuessComparer checker)
{
float guess = 0;
int result = checker.CheckGuess(guess);
int guesscount = 1;
var high = float.MaxValue;
var low = float.MinValue;
while (result != 0)
{
if (result > 0) //random is higher than guess
low = guess;
else// random is lower than guess
high = guess;
guess = (high + low) / 2;
guesscount++;
result = checker.CheckGuess(guess);
}
Console.WriteLine("Found answer in {0}", guesscount);
return guesscount;
}
public static void Find()
{
var checker = new GuessComparer();
int guesses = Find(checker);
}
}