int x = double y ?

 
int x;
double y = 1.00000000;

x = y;

This is a simplificated code from one of my scripts, that behaves strange. I found out why:
When I do this, x will be sometimes 0, sometimes 1. I couldn't figure out yet what does the result depend on.

If I use x = NormalizeDouble(y,4) * 10000, then it gives also contradicting results.

If I use
int x = StrToInteger(DoubleToStr(y,0));
everything works okay.

Shouldn't int x = double y be simple conversion?
 
Use MathRound(...) for more stable results

x=MathRound(NormalizeDouble(y,4)  * 10000);
 
irusoh1:
Use MathRound(...) for more stable results

x=MathRound(NormalizeDouble(y,4) * 10000);
Okay, it is another workaround, but it doesn't answer the question. How come, that I get different values for the int with the same double value?
Some people may have issues with their EAs, without even knowing it, I've seen a lot int,double mixtures in different EAs...
 
Try that

int x;
double y = 1.00000000;

x = y;
Print ("y=",DoubleToStr(y,16));
 
And what is it good for?
 
Zap:
int x;
double y = 1.00000000;

x = y;

I agree with you, Zap; if that code snippet would give you sometimes x==1 and sometimes x==0, then there would be a serious problem. However, if you actually have a code snippet where y is shown printed as 1.00000000 rather than being explicitly assigned (as in the example), then it can be understandable. Type casting from 'double' to 'int' is likely to be clipping the value rather than rounding it, while double number printing probably uses rounding rather than clipping.
Maybe you would want to use

x = MathRound( y );
 
I get the double y = 1.00000000 value from double PreviousBid/point - double Bid/point, which always needs to be an integer number. But I need this value in int, because I need it for Array line assingment, which requires int number. I know three solutions for correct working.What interesting is: without the workarounds, when simply I give the double result of PreviousBid/point - Bid/point to an int variable, it gives me different results, with the same Bid, PreviousBid values... Are there more numbers after the four digits that Bid uses? Or is it something else?
 
thw way floats are processed when you do calcilations on them sometimes they can round up to 0.99999999999 and sometimes
maybe 1.0000000001111 or something. If you truncate them to int you will get 0 or 1 depending on luck.

it's like your calculator, divide 1 by 3 then multiply by 3 you will get 0.99999999999 not 1.
 
irusoh1:

it's like your calculator, divide 1 by 3 then multiply by 3 you will get 0.99999999999 not 1.
but not 0. In my opinion 1.00000000999999999 should be as 1 as 1.0000000000000000. Either double to int conversion rounds, or cuts, or whatever, both should be int 1. But please explain me that I am wrong, I'll be happy...


irusoh1 wrote:

you will get 0 or 1 depending on luck.


See, thats what I am afraid of here. This would answer why people get different results when testing the same data. One EA, that does get different results, does a lot of math operations with doubles and ints mixed.
 
Exactly: the nature of the binary representation makes it impossible to represent some numbers exactly. In detail, the representation forms a sum of subsequent halfs (sum of 1/(2^k) for selected k from 1 to 50-something(?) in precision), and as a result, many fractions, in particular many rational numbers such as 1/3, are not represented exactly, but with numbers that are very close to exact but very, very slightly smaller. Often that error remains insignificant, but it's always there, and it can show up in many almost counter-intuitive effects, e.g. in that (1.0/3.0)*3.0 < 1.0.

With your calculation, you are thinking in terms of "since PreviousBid == Bid + N * Point, then N = PreviousBid / Point - Bid / Point, and N is an integer", which is totally agreeable, except for the possible representation error. Accounting for the possible errory you'd get "N [almost=] PreviousBid / Point - Bid / Point", which also translates into "N = MathRound( PreviousBid / Point - Bid / Point )". Generally you have to be most careful with division, and in all places take into account the possibility that "(A/B)*B < A" for some combinations of A and B; especially as you translate numbers to decisions by comparing them. For instance, a decision made on basis of a coinsidence of "X == Y" when X and Y are computed double numbers can be quite volatile, and should possibly be rephrased as "MathAbs(X-Y)<E" with E being a small number expressing the acceptable representation error.
 
Thank you for this exhaustive answer! I am aware of possible representation errors.

richplank wrote: "With your calculation, you are thinking in terms of "since PreviousBid == Bid + N * Point, then N = PreviousBid / Point - Bid / Point, and N is an integer"
Nope, I am thinking in terms of doubles myself, I just need the result in an int. I thought that in C++ double x = int y is a simple conversion, since there is nothing as DoubleToInt. And Math functions, as MathRound() keep a double a double.

There is nothing wrong with the double result of PreviousBid/Point - Bid/Point though, as it is always #.00000000000. The strange thing happens when I give this value to an int.

I made an EA, so you can see it with your eyes. I recommend it to run on a backtest, it errs about 1 out of 30. The EA makes a log.csv to tester/files, if you run it on backtest.

I tell you again: it is now theoretical talking, I know the working solution, and I use it in my EAs. But there are many guys out, who don't understand the issue this deep, and use ints and doubles mixed, thinking, that it works, or at least should work okay. But it doesn't.


int Ticks=0;
int loghandle;
double PrevBid;
double DiffDouble;
int DiffInt;

int deinit()
{
FileClose(loghandle);
return(0);
}

int start()
{
Ticks ++;
if (Ticks == 1)
{
loghandle = FileOpen("log.csv",FILE_CSV|FILE_READ|FILE_WRITE, ';');
PrevBid = Bid;
}
else
{
DiffDouble = Bid/Point - PrevBid/Point;
DiffInt = DiffDouble;

FileWrite(loghandle, "DiffInt: "+DiffInt," DiffDouble: "+DiffDouble);

PrevBid = Bid;
}
return(0);
}