double question: is this logic stupid - and about doubles and precision.

_vk_vk
edited November 2013 in Questions about Code

I'm trying to get the logic for this guessing algorithm. The goal is to find a number between 0 - 1. It is part of a bigger idea, so I'm gueesing a number that I pass to the function : P. I came up with the following code. So the two questions:

  1. simply, is this logic making sense? Is there a better way to do this?

  2. About precision. I'm testing for equality doing if ( abs(guess - number) > 0.0000000000000001) (16 places after the dot) if I do either if( guess != number) or add one more 0 to number above (precision var in code) than sometimes I endue in an infinite loop... (not happening in code below) Is this a problem of my algorithm? Also some times I got results like:

0.061002625506148545 < number was

0.06100262550614853 < I found

How is precision dealt with usually?

thanks

press any key to start over with a different number

 import java.util.Random;
double number;
double guess = 0.5; // first guess
int dir = 0;
int lastDir = 0;
double adjust = 0.1;
Random gen = new Random();
double precision = 0.0000000000000001;



void setup() {
  reset();
}

void draw() {
  guessThisNumber(number);
}

void keyPressed() {
  reset();
  loop();
}


void reset() {
  number = gen.nextDouble();
  guess = 0.5;
  dir = 0;
  lastDir = 0;
  adjust = 0.1;

  println("number is: " + number);
}


void guessThisNumber(double number) {
  int init = millis();
  while (Math.abs (guess - number) > precision) {

    if (lastDir == 0) {//first try to store dir
      double result = guess - number;
      dir = result < 0 ? 1 : -1; 
      lastDir = dir;
    }
    else {
      double result = guess - number;
      dir = result < 0 ? 1 : -1; 

      if (result > 0) {// guess is bigger");

        if (dir == lastDir) {// same dir as previous");

          // decrement -=
          guess -= adjust;

          //set dir to -1
          lastDir = -1;
        }
        else { // other dir than previous  ");

          //decrement adjust
          adjust /= 10;

          //increment +=
          guess += adjust;

          // set lastDir to 1;
          lastDir = -1;
        }
      }
      else if (result < 0 ) {// guess is smaller? ");
        if (dir == lastDir) {// same dir as previous");

          // increment +=
          guess += adjust;

          //set dir to 1
          lastDir = 1;
        }
        else {// other dir than previous  ");

          //decrement adjust
          adjust /= 10;

          //decrement -=
          guess -= adjust;

          // set dir to -1;
          lastDir = 1;
        }
      }
    }
  }        
  println("    found: " + guess );
  noLoop();
}
Tagged:

Answers

  • _vk_vk
    edited November 2013

    I updated the code This other code (same logic) have a Guesser class. Using three of them to guess colors and mimic it. Now funnier to run : )

    import java.util.Random;
    double r, g, b;
    Random rGen = new Random();
    Random gGen = new Random();
    Random bGen = new Random();
    Guesser rGuess= new Guesser();
    Guesser gGuess= new Guesser();
    Guesser bGuess= new Guesser();
    
    
    
    
    void setup() {
      size(1000, 800);
      newNumber();
      colorMode(RGB, 1);
      //frameRate(60);// so we can see...
      noStroke();
    }
    
    void draw() {
      background(0.01, 0.5, 0.85);
      fill(rGuess.guessThisNumber(r), gGuess.guessThisNumber(g), bGuess.guessThisNumber(b));
      ellipse(width/2 + width * 0.2, height/2, width * 0.6, width * 0.6);
    
      fill((float)r, (float)g, (float)b);
      ellipse(width/2 - width * 0.2, height/2, width * 0.6, width * 0.6);
    }
    
    void keyPressed() {
    newNumber();
      rGuess.reset();
      gGuess.reset(); 
      bGuess.reset();
    }
    
    
    void newNumber() {
      r = rGen.nextDouble();
      g = gGen.nextDouble();
      b = bGen.nextDouble();
        //println("number is: " + number);
    }
    
    
    class Guesser {
      double guess;
      int dir ;
      int lastDir;
      float adjust ;
      final double precision = 0.0000000000000001;
    
      Guesser() {
        reset();
      }
    
    
      float guessThisNumber(double number) {
        int init = millis();
    
        if (Math.abs (guess - number) > precision) {
    
          if (lastDir == 0) {//first try to store dir
            double result = guess - number;
            dir = result < 0 ? 1 : -1; 
            lastDir = dir;
          }
          else {
            double result = guess - number;
            dir = result < 0 ? 1 : -1; 
    
            if (result > 0) {// guess is bigger");
    
              if (dir == lastDir) {// same dir as previous");
    
                // decrement -=
                guess -= adjust;
    
                //set dir to -1
                lastDir = -1;
              }
              else { // other dir than previous  ");
    
                //decrement adjust
                adjust /= 10;
    
                //increment +=
                guess += adjust;
    
                // set lastDir to 1;
                lastDir = -1;
              }
            }
            else if (result < 0 ) {// guess is smaller? ");
              if (dir == lastDir) {// same dir as previous");
    
                // increment +=
                guess += adjust;
    
                //set dir to 1
                lastDir = 1;
              }
              else {// other dir than previous  ");
    
                //decrement adjust
                adjust /= 10;
    
                //decrement -=
                guess -= adjust;
    
                // set dir to -1;
                lastDir = 1;
              }
            }
          }
        }        
        //println("    found: " + guess );
        return (float) guess;
      }
    
    
      void reset() {
        guess = 0.5;
        dir = 0;
        lastDir = 0;
        adjust = 0.0015; //also speed
      }
    }//eof Guesser
    
  • Answer ✓

    It is recommended to never use == or != with floating point numbers, precisely because of rounding and precision issues.

    You can check if the absolute value of the difference between the number and the target is below a threshold, instead.

  • Thanks, so I was going in the right direction. Isn't there a constant for this? I think maybe e... never mind I'll google it.

  • Search for epsilon, but basically, it depends on the order of magnitude to your values: you don't compare values going up to one million the same way you compare values around a millionth.

Sign In or Register to comment.