Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
74 user(s) are online (60 user(s) are browsing Forums)

Members: 1
Guests: 73

walkero, more...

Headlines

 
  Register To Post

gcc bug or am I a looser?
Just popping in
Just popping in


See User information
Hi everybody,

I was testing a part of my code when I discovered something strange.
I was testing (function AmawIn) if a variable a is within a range [b,c] and when a was equal to b or c the result could be false.
Changing the types worked but not always. I changed the code testing different algorithms of AmawIn as you can read.
I am using gcc 11.3 (the last adtools). For info, I have just compiled the code with gcc Debian 11.3 with the same output.
After testing a lot, I have got no more ideas.
I hope someone will help me.
I compile with
Quote:
g++ -std=c++11 -athread=native -o test-anim test-anim.cc

Here is the code.
#include <iostream>
#include <cmath>
#include <exec/types.h>
using namespace std;
/*
template <class T>
bool AmawIn(const T a, const T b,const T c) {

//T aa=a,bb=b,cc=c;
//    if (b > c) { T tmp=bb; bb = cc; cc = tmp;}
    return !(a<b) && !(c<a);
}
*/

/*
bool AmawIn(float64 a, float64 b, float64 c) {

    if ( ( ( a >= b) &&  (a <= c)) || (( a >= c) && ( a <= b)) ) return true;
        else { cout <<"Inside AmawiI ( a="<<a<<" b="<<b<<" c="<<c<<")"<<endl;
        return false; 
    }
}
*/

/*
bool AmawIn(const float64 a, const float64 b,const float64 c) {

//T aa=a,bb=b,cc=c;
//    if (b > c) { T tmp=bb; bb = cc; cc = tmp;}
    return !(a<b) && !(c<a);
}

*/

bool AmawIn(const float64 a, const float64 b,const float64 c) {

    return !(
a<b) && !(c<a);
}

int main(int argcchar *argv[]) {

    
bool stopp false;
    
bool back true;
    
bool infinite false;

    
float64 animold;
    
int32 compteur 0;

    
int32 animt 1;
    
float64 animS 1.;
    
float64 animE 4.;
    
float64 animV 0.2;
    
float64 animSnew animS;
    
float64 animEnew animE;
    
float64 anim;

    
int32 delay1;
    
int32 delay2;
    
int32 delay3;

    if (
animV>=1) {
        
delay1 delay2 delay3 0;
    } else {
            
delay1 static_cast<int>( 1./(animV*2));
            
delay2 static_cast<int>( -1.+1./animV);
            
delay3 static_cast<int>( 1./animV);
    }

    if (
animV == 0.5delay2 2;
    if (
backanimt 2;
    if (
animS>animEanimV *= -1;

    if (
back) {
        if (
animS<animEanimEnew =animE delay1 animV;
        if (
animS>animEanimSnew animS delay2 animV;
    }

    
anim animSnew;
    
cout <<endl<<"    (animS = "<<animS<<", animE = "<<animE<<", animV = "<<animV<<")";
    
cout <<endl<<"    (animS = "<<animSnew<<", animE = "<<animEnew<<", animV = "<<animV<<")"<<endl;

    for (
int i=0; (i<1000) && !stopp; ++i) {

        if (
i%12==0cout <<endl;

        
animold anim;
        
cout <<anim<<", ";

        if (
animt 0) {
            
anim += animV;
            if (!
AmawIn(animanimSnewanimEnew ) ) {    //[color=FF6600]HERE IS THE PROBLEM[/color]
                
cout <<"( in AmawIn: "<<anim<<" not in "<<animSnew<<":"<<animEnew<<")"<<endl;

                if ( 
fabs(anim-animSnew) < fabs(anim-animEnew) ) anim animS;
                    else 
anim animE;

                if (!
infinite) --animt;
                if (
back) {
                    
animV*=-1;
                    if (
animt>0) {
                        if (
animS<animEanim =animEnew animV;
                        if (
animS>animEanim animE delay3 animV;
                    }
                    
cout <<endl<<endl<<"    back commencé (animS = "<<animSnew<<", animE = "<<animEnew<<", animV = "<<animV<<")"<<endl;
                } else if ( (
animt>1) || ( (animt==1) && infinite ) )     anim animS;
            }
        }

        if (
anim==animold) ++compteur;

        if (
compteur4stopp true;
    }
    
cout <<endl;

return 
0;
}



Here is the output
(animS 1animE 4animV 0.2)
    (
animS 1animE 4.4animV 0.2)

11.21.41.61.822.22.42.62.833.2
3.43.63.844.2, ( in AmawIn4.4 not in 1:4.4//[color=FF6600]HERE IS THE PROBLEM[/color]


    
back commencé (animS 1animE 4.4animV = -0.2)
4.243.83.63.43.23
2.82.62.42.221.81.61.41.2, ( in AmawIn1 not in 1:4.4//[color=FF6600]HERE IS THE PROBLEM[/color]


    
back commencé (animS 1animE 4.4animV 0.2)
111
11,

Since a lot of months without an amiga to love, I was lost.
Now I feel happiness again with a Sam Flex 800 .
Go to top
Re: gcc bug or am I a looser?
Just can't stay away
Just can't stay away


See User information
@yescop

Try "std::fixed << std::setprecision(8)" when printing those numbers. 8 or more, I don't remember how many digits were exactly required but it should show the issue with those floating point numbers.

Go to top
Re: gcc bug or am I a looser?
Home away from home
Home away from home


See User information
@yescop

It's not a gcc bug so you must be a looser

To be serious though, you are incrementally adding 0.2 in decimal ie base 10, to a floating point number stored in binary ie base 2. But 2 / 10 cannot be exactly expressed as base 2 fraction (in the same way that 1/ 3 can't be exactly expressed in a base 10 fraction (ie 0.3333333...) so each time you accumulate a small rounding error, so the final value you compare is slightly more than 4.4 and so your program correctly reports that it's outside the range.

Go to top
Re: gcc bug or am I a looser?
Just popping in
Just popping in


See User information
@yescop
Thanks for taking time to read my source and answer.

Capehill, the precision is 16 (using double).
Broadblues, I am not a looser but a too confident person.
I was thinking wrongly that the comparison in gcc was smarter.
For example, if a=1.0 and b=1.0, a==b would always return true.
But it is not true because the comparison will examine all digits (here 16) and not only a few (here only one digit, smarter as the variables used in my code were equal to numbers from 1 to 4 with a step of 0.2) and as you wrote, the conversion is not precise.

Since a lot of months without an amiga to love, I was lost.
Now I feel happiness again with a Sam Flex 800 .
Go to top
Re: gcc bug or am I a looser?
Home away from home
Home away from home


See User information
@yescop

Quote:

the precision is 16 (using double).

float or double you would get the same kind of problem.
Quote:

Broadblues, I am not a looser but a too confident person.

Of course not, I was just joking based on your question title

Quote:

I was thinking wrongly that the comparison in gcc was smarter.
For example, if a=1.0 and b=1.0, a==b would always return true.


In fact it will, the problem was that after your progressive calculations a was 1.0 and b 0.9999999 or in your specific case perhaps 4.4 and 4.399999

Quote:

But it is not true because the comparison will examine all digits (here 16) and not only a few (here only one digit, smarter as the variables used in my code were equal to numbers from 1 to 4 with a step of 0.2) and as you wrote, the conversion is not precise.


It's an easy trap to fall into. If you had chosen 0.25 as the interval you might have found it worked at first until later when you changed the step to 0.2, so it's good in a way that you found it sooner rather than later.

I would convert your iterator to an integer, multipled by 10 so that you go in steps of 2 (instead of 0,2)

Then you can make an exact comparison in the range 0 to 44 and if you need the value as a float calculate it with a cast

value = ((float)iterator) / 10.0

Go to top
Re: gcc bug or am I a looser?
Just can't stay away
Just can't stay away


See User information
@yescop

Just to clarify, by precision I meant cout output's display precision (how many digits you see), instead of amount of bits in variables (float or double).

Go to top
Re: gcc bug or am I a looser?
Home away from home
Home away from home


See User information
@Capehill

nope..

In math you learn about infinities, max and min number are infinities, another infinity is numbers between 1.0 to 2.0. to store an infinite number, you will need infinite space.

In a double some bits are used for exponent, another is fractions.
1/1, ½,1/4,1/8,1/16,1/32,1/64,
When you run out of bits you lose the resolution / accuracy.

https://en.wikipedia.org/wiki/Double-p ... ion_floating-point_format

some other stuff worth reading.

https://en.wikipedia.org/wiki/Repeating_decimal

Anyhow stuff like this is worth knowing when you are looking for dark energy, and dark matter.

(NutsAboutAmiga)

Basilisk II for AmigaOS4
AmigaInputAnywhere
Excalibur
and other tools and apps.
Go to top
Re: gcc bug or am I a looser?
Just popping in
Just popping in


See User information
@broadblues and all

In the meantime, I wrote this code. May be for someone it is overkill but it works well. Your solution using int is a good idea but not suitable in my case.

Here is the code for all who wants to know and feel to use it freely.
It is in C++

template <class T>
bool AmawIn(const T a, const T b,const T c) {

T bb=b,cc=c;
T eps std::numeric_limits<T>::epsilon()*100;
    if (
c) { T tmp=bbbb cccc tmp;}
    if ( (
a>bb) && (a<cc)) return true;
    if ( (
fabs(a-bb) < eps) || (fabs(cc-a) < eps) ) return true;
    return 
false;
}


Capehill, I had understood your purpose and used this to display the numbers
cout <<std::fixed<<std::setprecision(16)<<"(Amawin:: a="<<a<<" b="<<bb<<" c="<<cc<<" epsilon="<<eps<<")"<<endl;

Since a lot of months without an amiga to love, I was lost.
Now I feel happiness again with a Sam Flex 800 .
Go to top

  Register To Post

 




Currently Active Users Viewing This Thread: 1 ( 0 members and 1 Anonymous Users )




Powered by XOOPS 2.0 © 2001-2016 The XOOPS Project