[Solved] Float increment is not working properly & generating weird values

edited March 2014 in Questions about Code

Hi, In this code I am incrementing the float value so that speed of rotation of the points increament as distance increases but here this float increment is not working properly. Please try the code and check the console for the values. the value "j" is suppose to increment by 0.01 so the values should be 0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10..and so on but it prints something different.

Can any one explain this to me what I am missing because it never happened to me when I used program in C. I have never encountered such problem before in processing or may be I haven't noticed it ....

    Particle[] p = new Particle[100];
    float j=0.00;
    int k;
    void setup()
    {
      size(500, 500, P3D);
      for (int i=0;i<100;i++) {
        j=j+0.01;
        println(j);
        p[i] = new Particle(i*10, i*2+10, j );
      }
    }

    void draw() {
      background(0);
      for (int i=0;i<p.length;i++) {
        p[i].display();
        p[i].update();
        if (p[i].radius>width)
        {
          p[i].radius=10;
        }
      }
    }


    class Particle {
      float radius, ParticleNo;
      color c;
      float speed, v;
      Particle(float r, float p, float v) {
        radius = r; 
        ParticleNo = p;
        //c = (color) random(#000000);
        this.v = v;
        c = (color) random(#000000);
      }

      void display() {
        pushMatrix();
        translate(width/2, height/2);
        rotate(speed);
        noStroke();
        for (int i=0; i<=360; i+=360/ParticleNo)
        {
          pushMatrix();
          float x = radius * cos(radians(i));
          float y = radius * sin(radians(i));
          translate(x, y);
          //      if (i>300)fill(255,0,0);
          //      else
          fill(-1);
          ellipse(0, 0, 2, 2);
          popMatrix();
        }
        popMatrix();
      }

      void update() {
        speed=speed+v;
      }
    }

Answers

  • edited November 2013

    What you are seeing is the limits of representation for a float. In base 10 (numbers people normally think about) you cannot represent 1.0/3.0 exactly. Likewise in base 2 you cannot represent some numbers.

    If you want the numbers to have the same increment try using a power of 2 that is close to 0.01:
    - 0.015625, or 2.0^-6
    - 0.0078125, or 2.0^-7

  • edited November 2013

    Thanks asimes for your effort but it has been suggested by many programmers and also it was mentioned on the processing website in float reference here . They say incementing with any float is a bad idea because it starts doing the approximation.

    so the instead of using this

        float f = 0;
        for (int i = 0 ; i < 100000; i++) {  
          f = f + 0.0001;  // Bad idea! See below.
        }
    

    use this

        for (int i = 0; i < 100000; i++) {
          // The variable 'f' will work better here, less affected by rounding
          float f = i / 1000.0;  // Count by thousandths
        }
    

    So my Final code is here but still I am not getting the effect what I am trying to achieve

    Particle[] p = new Particle[100];
    int k;
    void setup()
    {
      size(500, 500, P3D);
      for (int i=0;i<100;i++) {
        float j = (i-40)/100.0;
        println(j);
        p[i] = new Particle(i*10, i*1+10, j );
      }
    }
    
    void draw() {
      background(0);
      lights();
      for (int i=0;i<p.length;i++) {
        p[i].display();
        p[i].update();
        if (p[i].radius>width)
        {
          p[i].radius=10;
        }
      }
    }
    
    
    class Particle {
      float radius, ParticleNo;
      color c;
      float speed, v, h;
      Particle(float r, float p, float _v) {
        radius = r; 
        ParticleNo = p;
        v = _v;
        c = (color) random(#000000);
       // h = random(10, 15);
      }
    
      void display() {
        pushMatrix();
        translate(width/2, height/2);
        rotate(speed);
        noStroke();
        for (int i=10; i<=360; i+=360/ParticleNo)
        {
          pushMatrix();
          float x = radius * cos(radians(i));
          float y = radius * sin(radians(i));
          translate(x, y);
          //      if (i>300)fill(255,0,0);
          //      else
          fill(-1);
          ellipse(0, 0,2,2);
          popMatrix();
        }
        popMatrix();
      }
    
      void update() {
        speed=speed+v;
      }
    }
    
  • edited November 2013 Answer ✓

    That is a better approach in the sense that you can more reliably use any number, it will always be "off" by a fixed amount.

    What I was trying to show is that adding by an approximation will over time make the approximation worse. Fractions that are a power of 2 are a special case because their sums can be represented accurately.

    Likewise in base 10 (not base 2 like floats):
    - 0.5 + 0.5 + 0.5… never causes a problem
    - 0.33333333 + 0.33333333 + 0.33333333… would continuously become less accurate if 0.33333333 is meant to be 1.0/3.0

Sign In or Register to comment.