DATA Step, Macro, Functions and more

Int gives wrong number

Reply
N/A
Posts: 1

Int gives wrong number

Hi guys,

i have a problem. - Im trying to truncate a number by the following procedure:

      &result. = int(round(&array.[&counter.],0.000000000000001)*(10**&array.[&counter.-1]))*(10**-&array.[&counter.-1]);

where &counter. is the number which need to be truncated, and &counter.-1 is the number og digits i want to truncate with.

For curtain numbers, this fails. - An example;

       int(round(67.1,0.000000000000001)*(10**6))*(10**-6);

which gives 67.09999999.

I have come to the conclusion, that it is the int function, which is the problem;

data _null_;

number = 67.1*100000;

number_int = int(number);

put number;
run;


This returns "6709999" as an example.

Any ideas what to do, to not run into this problem ?

Community Manager
Posts: 2,761

Re: Int gives wrong number

Moved this to for input from folks on SAS functions.

Super User
Super User
Posts: 6,500

Re: Int gives wrong number

There is nothing wrong with INT() function.  By ROUNDING() you have reduced the precision with which the number can be stored.  You can see the same effect by reducing the number of storage bytes.

Try this program to see the impact of throwing away some of the precision from a number like one tenth that cannot be represented exactly using binary numbers.

data _null_;

  fraction= 67 + 1/10 ;

  do trunc=8 to 3 by -1 ;

    number=trunc(fraction,trunc);

    number_int= int(round(number,0.000000000000001)*(10**6))*(10**-6);

    put trunc= number= number_int=;

  end;

run;

trunc=8 number=67.1         number_int=67.099999

trunc=7 number=67.1         number_int=67.099999

trunc=6 number=67.1         number_int=67.099999

trunc=5 number=67.099999905 number_int=67.099999

trunc=4 number=67.099975586 number_int=67.099975

trunc=3 number=67.09375     number_int=67.09375

Super User
Super User
Posts: 6,500

Re: Int gives wrong number

Move your exponents around so that you can round() to an integer.

This:

    number_int= int(round(number,0.000000000000001)*(10**6))*(10**-6);

Will become this:

    number_int= round(number*(10**15),1) *(10**-15);

Or to make it easier for your formula:

    number_int= round(number*(10**(9+6)),1) *(10**(-9-6));

Respected Advisor
Posts: 3,893

Re: Int gives wrong number

Hi Tom

I have no doubt that this is about precision and binary storage of floating point numbers but I still can't fully understand what's going on here. Can you please try and elaborate/explain a bit more?

In below sample code what I don't understand:

- Why can't I see the difference when printing the numbers using format "32.24"

- Why is there no difference in "case 2"?

data _null_;

  /** case1: 6710000 **/

  put  / '***** case1: 6710000 ******';

  number_calc = 67.1 * 100000;

  number_fixd  = 6710000;

  number_diff= number_fixd - number_calc;

  put number_calc= 32.24;

  put number_fixd = 32.24;

  put number_diff = 32.24 /;

  put number_calc = binary64.;

  put number_fixd = binary64.;

  /** case2: 10000 **/

  put / '***** case2: 10000 ******';

  number_calc = 0.1 * 100000;

  number_fixd  = 10000;

  number_diff= number_fixd - number_calc;

  put number_calc= 32.24;

  put number_fixd = 32.24;

  put number_diff = 32.24 /;

  put number_calc = binary64.;

  put number_fixd = binary64.;

  stop;

run;

***** case1: 6710000 ******

number_calc=6710000.000000000000000000000000

number_fixd=6710000.000000000000000000000000

number_diff=0.000000000931322574615470

number_calc=0100000101011001100110001011101111111111111111111111111111111111

number_fixd=0100000101011001100110001011110000000000000000000000000000000000

***** case2: 10000 ******

number_calc=10000.000000000000000000000000

number_fixd=10000.000000000000000000000000

number_diff=0.000000000000000000000000

number_calc=0100000011000011100010000000000000000000000000000000000000000000

number_fixd=0100000011000011100010000000000000000000000000000000000000000000

Thanks

Patrick

Contributor
Posts: 52

Re: Int gives wrong number


I concur with JakobKrogh that the issue is with the int() function.

data _null_;
   number = 67.1*100000;

   number_int1 = int(number);
   number_int2 = int(number+0.000000001);
   number_int3 = int(number+0.0000000001);
   number_int4 = round(number,1);

   put number= number_int1= / number_int2= number_int3= / number_int4=;
run;

one gets the following:

number=6710000 number_int1=6709999
number_int2=6710000 number_int3=6709999
number_int4=6710000

it turns out that:

int(number+0.0000000005)  = 6710000

Super User
Super User
Posts: 6,500

Re: Int gives wrong number

Nope.  Still the same problem.  You cannot represent that many distinct decimal digits using binary floating numbers.

Try this one.

data _null_;

   number0 = 67.1 * 10**5;

   do i=-1 to -10 by -1;

     number1 = number0+10**i ;    

     put i= Z3. +1 number1 =20.12 ;

   end;

run;


i=-01  number1=6710000.100000000000

i=-02  number1=6710000.010000000000

i=-03  number1=6710000.001000000000

i=-04  number1=6710000.000100000000

i=-05  number1=6710000.000010000000

i=-06  number1=6710000.000001000000

i=-07  number1=6710000.000000100000

i=-08  number1=6710000.000000010000

i=-09  number1=6710000.000000000000

i=-10  number1=6710000.000000000000

Super User
Super User
Posts: 6,500

Re: Int gives wrong number

Here's another fun one.

data _null_;

  one_tenth=0.1;

  one = 1;

  do _n_=1 to 10 ; ten_tenths + one_tenth; end;

  diff = one - ten_tenths ;

  put (_all_) (= best32.);

run;


one_tenth=0.1 one=1 ten_tenths=1 diff=1.1102230246251E-16

Valued Guide
Posts: 3,208

Re: Int gives wrong number

Computers are not doing the math in the decimal approach. They are BINARY, thare are 10 ways to understand that are:  yes/no.

See the docs SAS(R) 9.4 Language Reference: Concepts, Fourth Edition the decimal value 0.1 is an infinitely repeating reciproke in binary just like 1/3 =0.333... (wat is the last precision?)

Do the math the same in binary just as the processors (it is about that hardware level) are doing.

---->-- ja karman --<-----
Community Manager
Posts: 2,761

Re: Int gives wrong number

This fun topic -- numeric precision in SAS -- comes up quite a bit.  Jaap is correct: floating point math in computers is not the same as if you worked it out by hand.  There is an IEEE standard for how floating point numbers are represented in computers, and SAS follows that standard.

More here:

http://blogs.sas.com/content/sasdummy/2012/03/01/precision-in-sas-numbers/

Also this fun one: what is the difference between 0 and -0?

Chris

Ask a Question
Discussion stats
  • 9 replies
  • 354 views
  • 0 likes
  • 6 in conversation