界限和整数

Bounds and whole numbers

本文关键字:整数 界限      更新时间:2023-10-16

我正在阅读Bjarne Stroustrup的"使用c++编程原则和实践"。我正在做第四章练习4。

练习如下:

写一个程序来玩一个数字猜游戏。用户想到一个1到100之间的数字,你的程序会问问题来找出这个数字是什么(例如:"你想的数字小于50吗?")。你的程序应该能够在问不超过7个问题后识别数字。提示:使用<和><=操作符和if-else结构。

这很好,我已经很好地实现了。

我想我应该试着强迫自己,试着用循环来实现这个,每次都调整下界或上界。

下面是我的代码:
#include "std_lib_facilities.h"
int main( ){
  int count = 0;
  int lowerBound = 0;
  int upperBound = 100;
  string userInput = "";
  while ( lowerBound != upperBound ){
    // Increment count
    ++count;
    int halfRange = 0;
    // Make halfRange a while number, round up if any decimal portion.
    double range = ( upperBound - lowerBound ) / 2;
    int rangeDelta = range - (int)range;
    if ( rangeDelta != 0 )
      halfRange = (int)range + 1;
    else
      halfRange = range;
    cout << count <<": Is your number between " << lowerBound << " and " << lowerBound + halfRange << "? ";
    cin >> userInput;
    // Reset the bounds
    if ( userInput == "y" || userInput == "Y" )
      upperBound -= halfRange;
    else if ( userInput == "n" || userInput == "n" )
      lowerBound += halfRange;
    else {
      --count;
      cout << "Error! Answer could not be understood.";
    }
  }
  cout << "lowerBound: " << lowerBound << ", upperBound: " << upperBound << "nn";
  cout << "Your number is: " << lowerBound << "n";
  return 0;
}

问题?当涉及到有小数部分的数字时,使用整数除法,就会把小数部分丢掉。如果你使用数字48,程序会猜测到47和47。

有什么线索能让我继续吗?我想我已经很接近了,但如果你能帮忙的话,我会很感激的。

谢谢,马特

 double range = ( upperBound - lowerBound ) / 2;

这一行会给你带来问题,因为所有的操作数都是int,因此它被计算为int而不是double。如果这不是故意的,修改2 -> 2.0来解决这个问题。

int rangeDelta = range - (int)range;

你确定你不需要double rangeDelta

我认为你的代码中仍然存在一个问题(即使之前发出的错误已经修复):应该清楚的是,上限和下限都包含在剩余的可能数字中,这从你的代码中并不清楚:在第一个问题中,如果我回答'y',新的间隔是[0,50],如果我回答'n',新的间隔是[50,100],这是错误的!50不应包括在第二个间隔中。

要解决这个问题,您应该将边界更新更改为如下内容:

if ( userInput == "y" || userInput == "Y" )
   upperBound = lowerBound + halfRange;
else if ( userInput == "n" || userInput == "n" )
   lowerBound = lowerBound + halfRange + 1;

现在最后一个问题仍然有一个问题,它永远保持不变。问题是,当range=1时,你也得到了halfrange=1,问题保持不变。

要解决这个问题,应该将四舍五入到范围内。只需像这样定义它:
int halfRange = ( upperBound - lowerBound ) / 2;

,现在你的代码应该可以工作了。下面是我将用于while循环的代码:

while ( lowerBound != upperBound ){
// Increment count
++count;
int halfRange = ( upperBound - lowerBound ) / 2;
int midpoint = lowerBound + halfRange;
cout << count <<": Is your number between " << lowerBound << " and " << midpoint << "? (both included) ";
cin >> userInput;
// Reset the bounds
if ( userInput == "y" || userInput == "Y" )
  upperBound = midpoint;
else if ( userInput == "n" || userInput == "n" )
  lowerBound = midpoint + 1;
else {
  --count;
  cout << "Error! Answer could not be understood.";
}

}

注意,现在我们只使用整数,根本没有使用双精度数!如果您使用整数,请尽量避免传递double,并使用整数除法和取模来处理它们(并且不要使用double来表示整数)。

希望有帮助!

您也可以使用数组来实现这一点,这将在第4章中解释。

int min = 1;    // range for our guessing game
int max = 10;
int guess = 0;  // value to keeep track of guessing
char choice = ' ';
vector<int>v;
// put all our values into a vector
for(int i = min; i <= max; i++) {
    v.push_back(i);
}

while (v.size() != 1) {   // if there is only one value left, no guessing needed. jump out of loop
    guess = v[v.size()/2];   // find median
    cout << "nIs your number less than " << guess << "? (y/n)n";  // ask user for hint
    cin >> choice;
    if(choice == 'y') { //y: value is below median, pop values of median and above out of our range of values
        for(int i = 0; i < v.size(); i++)
        v.pop_back();
    }
    else {  // n: value is median or above. erase the lower values out of our range of values
        for(int i = 0; i < v.size(); i++){
            v.erase(v.begin());
        }
    }
} // end while
cout << "The number is " << v[0] << "n";