LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

fmod not calculating remainder correctly

It looks to me like the fmod() function is not computing certain remainders correctly.  If I try it with the following parameters:

dDividend = 100.0E-9;
dDivisor = 0.25E-9;

dRemainder = fmod (dDividend, dDivisor);

I should get dRemainder = 0.0, but instead I get dRemainder = dDivisor.

It looks like if dDividend is a multiple of dDivisor then dRemainder is always dDivisor.
0 Kudos
Message 1 of 11
(6,007 Views)

Hi Snood1,

I believe that your problem deals with the way the machine represents number. IEEE 754 standard does not allow all floating points to be represented exactly. Let's try 100E-9 and 0.25E-9 with the following link and you can now understand where your problem comes from.

Here is a long thread dealing with IEEE 754 and LabVIEW. Same considerations should be taken into account with CVI

Best regards,

Message 2 of 11
(5,999 Views)
Mathieu,

Thanks for the help.  I was not taking floating point number representation into account.

-Joel
0 Kudos
Message 3 of 11
(5,800 Views)

I still have doubt after see the IEEE 754.Could you give me a favor  ?thank you ! My question is :

 BYTE  IMEI[16]="";  //unsigned char =BYTE
 int  YY,MM,DD ;

GetSystemDate (&MM, &DD, &YY);  //int GetSystemDate (int *Month, int *Day, int *Year);
IMEI[10] = fmod(DD,10);                   //double fmod (double Dividend, double Divisor);

a few days before, i found that when DD=15,the IMEI[10]=0.  follow the IEEE 754 :15=1*2^3*1.875,10=1*2^3*1.25,

so 1.875 willl be divided by 1.25 and reminder equal zero,it is also can express as that :15/10=1*2^3*(1.875/1.25)=0.

is it right?

And I have another doubt that :there are about 20 PCs,only 2 of them give the IMEI[10]=0 and others give IMEI[10]=5.

wating for your attention,thanks.

--------------------------------------
on the road to windows
liuerbin@hotmail.com
0 Kudos
Message 4 of 11
(5,583 Views)
Hi Robin,

I have no clue for now... If someone knows Smiley Surprised let us know

Can you give a try to the following code on the two PCs that "do not work" as we expect and give us the results: DebugPrintf("%f", fmod(15.0, 10.0));

Regards.


Message Edité par Mathieu Steiner le 03-18-2008 10:43 AM
0 Kudos
Message 5 of 11
(5,572 Views)
Hello all,

As Mathieu pointed out in the second post on this forum, complications can arise when dividing floating point numbers if the divisor exactly divides the dividend.  The forum linked to by Mathieu above is very helpful in explaining why this happens.  Essentially, it is because a floating point number which appears to be 2.5 E-9, may actually be 2.5000000001 E-9, so when it divides 5.0, the result would be 1, with a remainder of 2.49999999999999, rather than 2, with a remainder of zero.

However, when using the fmod function with dividends and divisors of 15 and 10 (or 1.875 and 1.25) you should never get a remainder of zero.  Furthermore, it should yield the same result on all machines that CVI is installed on.  Could you verify the results that you are getting and confirm the erroneous results on the 2 "bad" computers, making sure to check that your input to fmod is the same in all cases?

I noticed that you are using multiple data types to represent these values as well.  Make sure that you are passing the right data types into these functions and then checking the result that is stored in a variable of the right data type.  For instance, the fmod function should take 2 doubles as input and store the result in a double.  I hope that helps!


Regards,


Marty H.
National Instruments
0 Kudos
Message 6 of 11
(5,542 Views)

Thank you for your advice.when I use "int   IMEI[16]="" ,the results is ok.now I use MM%10 instead fmod(MM,10).

But using the wrong dada types in the program,some PCs can run ok,othes not.

 The confusing program is as follow:

------------------code-------------------------------------------

int  YY,MM,DD;                                                                                                                      
 BYTE  IMEI[16]="";


 GetSystemDate (&MM, &DD, &YY);    YY=2008,MM=3,DD=19

 IMEI[6]  = YY-2000;                                                                                                                           
 IMEI[7]  = MM/10;                                                                                                                       
 IMEI[8]  = fmod(MM,10);                                                                                                                 
 IMEI[9]  = DD/10;                                                                                                                       
 IMEI[10] = fmod(DD,10);

--------------------bad PCs---------------------------------------

if use BYTE IMEI[16],

one PC gives the wrong result when running "  IMEI[8]  = fmod(MM,10) ",

the other PC gives the wrong when running "IMEI[10] = fmod(DD,10)",

 further more, the two PCs both give right result only when there first  running , I confuse by them.

--------------------------------------
on the road to windows
liuerbin@hotmail.com
0 Kudos
Message 7 of 11
(5,529 Views)

---------------- memory -------------------------------------------

first running

the memory give the right data:

 00          08        01            03         00          09

 IMEI[7]  IMEI[6]   IMEI[9]   IMEI[8]   IMEI[11]    IMEI[10].

 

after first running

the memory give the right data:

 00          08        01            00        00          09

 IMEI[7]  IMEI[6]   IMEI[9]   IMEI[8]   IMEI[11]    IMEI[10].

 -----------------------Question--------------------------------------------------

I donot know why their first running is ok?

 The fmod  function needs using double dada type.When using the int dada type , the compiler may be confusing when the program runs on the bad PCs?   

How can I validate the difference of their compilers ?

--------------------------------------
on the road to windows
liuerbin@hotmail.com
0 Kudos
Message 8 of 11
(5,528 Views)
Hi Robin,

I would recommend you step through this code using LabWindows/CVI built in debugging tools and check the value of each variable immediately before and after each function call, so that we can narrow down where the problem is coming from.  I tried this code on my machine and it worked as expected.  I am wondering if perhaps the date is off for the 2 PCs that give incorrect results.  That would explain why you get different values from what is expected.

You can also compare the values from the first run on these machines with the values the second time this code runs to see what is different.  It could be that one of these variables is being accidentally set somewhere else in your code.  Differences in the PCs that you run this code on should not affect the outcome of this code, and it should not change from one iteration to the next if the inputs are all the same, so I would recommend some step-by-step debugging to locate the source of the bad results.
Regards,


Marty H.
National Instruments
Message 9 of 11
(5,517 Views)
Hi,Marty ,
 When the application program first run, IMEI[8] is give the result as expect ;but after first running ,it give the rusult equal zero .
Using debugging  tool ,   before and after executing IMEI[8]  = fmod(MM,10);the local variable MM is not changed.Because I cannot step into the fmod function , so I just know IMEI[8] gives a wrong result  from the memory .
 How can I step into the fmod function ?  
     
--------------------------------------
on the road to windows
liuerbin@hotmail.com
0 Kudos
Message 10 of 11
(5,487 Views)