BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Tiri6
Fluorite | Level 6

Hi everybody,

 

i need help with the MOD function with a big number.

 

 

data asd;

format check 30.;

check = 310300000604156791754311182900;

Y =mod(check,97);

run;

 

i can't do this data step because of this error:

 

NOTE: Invalid argument to function MOD(3.103058E29,97) at line 2667 column 4.

check=310300000604156791754311182900Y=. _ERROR_=1 _N_=1

NOTE: Mathematical operations could not be performed at the following places. The results of the operations have been set to missing values.

Each place is given by: (Number of times) at (Line):(Column).

1 at 2667:4

NOTE: The data set WORK.F has 1 observations and 2 variables.

NOTE: DATA statement used (Total process time):

 

Could you please help me?

Many thanks.

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

@novinosrin wrote:

Can this be helped with a notes on how the math works(when you have moment plz) 


It's no rocket science, really. 🙂

 

Mathematically, we can write the integer in question as

3*10**29 + 1*10**28 + 0*10**27 + ... + 9*100 + 0*10 + 0*1

 

Results from algebra (keyword: quotient ring Z/nZ) imply that

(1)  mod(a+b,c)=mod(mod(a,c)+mod(b,c),c)
(2)  mod(a*b,c)=mod(mod(a,c)*mod(b,c),c)
(3)  mod(mod(a,c),c)=mod(a,c)

for "all" integers a>=0, b>=0 and c>0. ("All" that the MOD function in SAS allows. Note also that for negative a or b the MOD function in SAS behaves in a way that equation (1) does not hold in general.)

 

So, we can compute the desired result by the rules above as

mod(3*mod(10**29, 97) + 1*mod(10**28, 97) + ... + 0*mod(10**0, 97), 97)

The sum in the argument of the outer MOD function is accumulated in the DO loop of the second data step (variable S), starting from the rightmost term. The outer MOD function is called in the final assignment statement (y=...).

 

(Side note: If there was a risk that the sum in S exceeds constant('exactint')=9.007...E15, we could apply the MOD function in each iteration of the DO loop, i.e., insert s=mod(s,97); before the END statement. But we are far away from that risk: s=3494 in the example.)

 

Obviously, a lookup table for mod(10**k, 97), k=0, 1, ..., 29, is quite helpful for the above calculation. This lookup table (in fact an extended version of it: for k=0, ..., 100) is provided by the first data step, which also makes use of rules (2) and (3).

View solution in original post

8 REPLIES 8
Tom
Super User Tom
Super User

SAS uses 8 byte floating point numbers so there is no way to store that many digits.

 

Tiri6
Fluorite | Level 6

Ok thanks.

Are there other functions that let me to do this calculate?

 

ballardw
Super User

@Tiri6 wrote:

Hi everybody,

 

i need help with the MOD function with a big number.

 

 

data asd;

format check 30.;

check = 310305801604100571754311182900;

Y =mod(check,97);

run;

 

i can't do this data step because of this error:

 

NOTE: Invalid argument to function MOD(3.103058E29,97) at line 2667 column 4.

check=310305801604100494425342345216 Y=. _ERROR_=1 _N_=1

NOTE: Mathematical operations could not be performed at the following places. The results of the operations have been set to missing values.

Each place is given by: (Number of times) at (Line):(Column).

1 at 2667:4

NOTE: The data set WORK.F has 1 observations and 2 variables.

NOTE: DATA statement used (Total process time):

 

Could you please help me?

Many thanks.

 

 


Your "number" has exceeded the storage limits of SAS. Note that the displayed numeric value is not the same as you attempted to enter, highlighted above.

 

Please note from the documentation:

MOD returns a missing value if the remainder cannot be computed to a precision of approximately three digits or more. In this case, SAS also writes an error message to the log.

Since numbers like your example are not actually stored correctly any calculation on them is going to be somewhat unreliable in any case.

 

Without knowing what you actually need it hard to suggest an appropriate work around.

FreelanceReinh
Jade | Level 19

Hi @Tiri6,

 

As @Tom has pointed out already, almost all integers of this length cannot be stored in a numeric variable in SAS without a substantial loss of precision (which would render any MOD function value useless). Note the discrepancy between your numeric literal (ending in ...2900) and the corresponding value in the log (ending in ...5216).

 

However, it is no problem to store this string of digits in a character variable and apply some basic mathematics to obtain the desired result:

/* Create auxiliary table containing the values m=mod(10**k, 97) for k=0, ..., 100 */

data tmp;
m=1;
do k=0 to 100;
  m=mod(m,97);
  output;
  m=10*m;
end;
run;

/* Compute y=mod(check,97) */

data asd(keep=check y);
length check $101;
check = '310305801604100571754311182900';
do i=length(check) to 1 by -1;
  set tmp;
  s+input(char(check,i),1.)*m;
end;
y=mod(s,97);
output;
stop;
run;

Of course, 30 instead of 101 would be a sufficient length for this particular value of CHECK (and similarly 29 instead of 100 a sufficient end value of the DO loop in the first data step). I've just chosen a larger value to allow for even longer integers (of up to 101 digits).

novinosrin
Tourmaline | Level 20

Sir @FreelanceReinh   That kinda brilliance is incredible and teasing. Why do you have to make "wannbe-reinhard's" cry? Where i have sinned? Can this be helped with a notes on how the math works(when you have moment plz) 

FreelanceReinh
Jade | Level 19

@novinosrin wrote:

Can this be helped with a notes on how the math works(when you have moment plz) 


It's no rocket science, really. 🙂

 

Mathematically, we can write the integer in question as

3*10**29 + 1*10**28 + 0*10**27 + ... + 9*100 + 0*10 + 0*1

 

Results from algebra (keyword: quotient ring Z/nZ) imply that

(1)  mod(a+b,c)=mod(mod(a,c)+mod(b,c),c)
(2)  mod(a*b,c)=mod(mod(a,c)*mod(b,c),c)
(3)  mod(mod(a,c),c)=mod(a,c)

for "all" integers a>=0, b>=0 and c>0. ("All" that the MOD function in SAS allows. Note also that for negative a or b the MOD function in SAS behaves in a way that equation (1) does not hold in general.)

 

So, we can compute the desired result by the rules above as

mod(3*mod(10**29, 97) + 1*mod(10**28, 97) + ... + 0*mod(10**0, 97), 97)

The sum in the argument of the outer MOD function is accumulated in the DO loop of the second data step (variable S), starting from the rightmost term. The outer MOD function is called in the final assignment statement (y=...).

 

(Side note: If there was a risk that the sum in S exceeds constant('exactint')=9.007...E15, we could apply the MOD function in each iteration of the DO loop, i.e., insert s=mod(s,97); before the END statement. But we are far away from that risk: s=3494 in the example.)

 

Obviously, a lookup table for mod(10**k, 97), k=0, 1, ..., 29, is quite helpful for the above calculation. This lookup table (in fact an extended version of it: for k=0, ..., 100) is provided by the first data step, which also makes use of rules (2) and (3).

novinosrin
Tourmaline | Level 20

Thank you so much! Cheers!

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 8 replies
  • 2442 views
  • 6 likes
  • 5 in conversation