n E Z => sin(n*pi) = -1 ?

the problem is simple at the first glance. if n is an integer, than sin(n*pi) should be "0". But it gives "-0,999".
isInt = @(n) sin(n*pi);
isInt(100000000000000000000000000000);
I get that the number should be small since the computation doesnt go beyond 10^17, but if I give 5, the result is "6*10^-16". Still, is not "0". How can I overcome this problem? is there a method? I need to solve the problem of "integer". It should be "exact integer". I couldn't find a way to get over it. Do you have any idea?

Réponses (4)

Steven Lord
Steven Lord le 21 Juil 2022

2 votes

Use the sinpi function.
n = 100000000000000000000000000000;
sinpi(n)
ans = 0

6 commentaires

James Tursa
James Tursa le 21 Juil 2022
Modifié(e) : James Tursa le 21 Juil 2022
Note that this n value can't even be represented exactly in IEEE double precision:
n = 100000000000000000000000000000;
fprintf('%30.0f\n',n)
99999999999999991433150857216
eps(n)
ans = 1.7592e+13
So, while the sinpi( ) function gets this particular answer correctly, it is questionable whether this calculation even makes sense given the range of values involved. Every IEEE double number in the range of n is an integer. The closest distance between IEEE doubles in that range is about 1.7592e13. I doubt OP even realizes that he isn't actually using 1e29*pi, but is using something "nearby" as close as IEEE double precision can represent, and "nearby" could mean as far as about 1e13.
Emirhan Solmaz
Emirhan Solmaz le 21 Juil 2022
Thank you both...
Dear James, I don't have a deep knowladge but I know that it can't be stored as exact number, but IEEE. Actually, a big part of the question was related to that. Is not there any way to store the numbers as exact integers? I really need that. I attempted a couple of times to find a way, but as you guessed, I failed. I really wasn't aware such a problem would be exist, since a computer's main job is adding integers. My ignorance. I didn't know at all.
Emirhan Solmaz
Emirhan Solmaz le 21 Juil 2022
Dear Steven, I tried your way with this :
n = 1.00000000000000000000000000001;
sinpi(n)
and it gave "0" again but it shouldn't. So doesn't work in the way I want.
James Tursa
James Tursa le 21 Juil 2022
Modifié(e) : James Tursa le 21 Juil 2022
@Emirhan Solmaz You have the same basic problem with this number ... it can't be represented exactly in IEEE double precision. You only get about 16-17 decimal digits of precision, and your trailing 1 is 29 decimal digits away from the leading 1. The closest IEEE double precision number to this is in fact exactly 1 with no non-zero trailing digits. In other words, when the parser reads the characters 1.00000000000000000000000000001 and turns it into an IEEE double precision number for downstream use, the result is exactly 1. Yes one of the computer's main jobs is to add integers, or in this case doubles with integer values, but you still have to stay within the precision limits of the type you are using and your examples do not do that for double precision.
If you need this extra precision, you will need to resort to solutions like others have already posted involving the Symbolic Toolbox.
Maybe you can take a step back and tell us what larger overall problem you are solving and why you think you need this extra precision in order to solve it. I suspect this might not be the only issue.
Emirhan Solmaz
Emirhan Solmaz le 21 Juil 2022
I see... I try to write a complex algorithm (it is to me) and in a part of it I need converting decimal numbers to integers. But decimals are not equally long, so I wrote a function for that and it includes while loop. But, I don't know why exactly, it goes beyond the IEEE limits sometime. So, it fails. I tried different methods to change it, lastly I found the sin(n*pi) method which I thought it would work but I hit the same wall again because of different reasons. Basicly I need a way to calculate formulas beyond the limits of IEEE. which I suppose it is not possible. is it?
James Tursa
James Tursa le 21 Juil 2022
Modifié(e) : James Tursa le 21 Juil 2022
"Basicly I need a way to calculate formulas beyond the limits of IEEE. which I suppose it is not possible. is it?"
Yes, it is. Use the Symbolic Toolbox as others have already suggested.
That being said, I suspect that your "algorithm", which you haven't discussed or shown us, may be producing garbage if you need 30 or more decimal digits of precision to calculate results. What else is going into this calculation and are you carrying enough precision in every variable to make the result meaningful? Can you post this code?

Connectez-vous pour commenter.

Stephen23
Stephen23 le 21 Juil 2022

1 vote

n = sym(100000000000000000000000000000)
n = 
100000000000000000000000000000
sin(n*pi)
ans = 
0

1 commentaire

James Tursa
James Tursa le 21 Juil 2022
Modifié(e) : James Tursa le 21 Juil 2022
Note that sym( ) here is doing the conversion based on its calculated "intent" of the user, since the actual number that gets passed to sym( ) isn't 100000000000000000000000000000 but something "nearby" as close as IEEE double precision can represent:
n = 100000000000000000000000000000;
fprintf('%30.0f\n',n);
99999999999999991433150857216
Also, there is another subtle conversion going on in the background. The double precision pi value is converted to its symbolic version based again on its calculated "intent" of the user. That is, here is the actual double precision pi value converted to decimal:
fprintf('%60.55f\n',pi);
3.1415926535897931159979634685441851615905761718750000000
But The product n*pi results in a conversion of this to the "exact" symbolic pi before sin( ) is called:
n = sym(n)
n = 
100000000000000000000000000000
n*pi
ans = 
Personally, I prefer to have these silent conversions made explicit in the code so I don't inadvertently get bit downstream. E.g., I typically would calculate this instead up front and use it downstream so there is no possible ambiguity:
sympi = sym('pi')
sympi = 
π

Connectez-vous pour commenter.

KSSV
KSSV le 21 Juil 2022

0 votes

n = vpa(100000000000000000000000000000) ;
vpa(sin(n*pi))
ans = 
0.000000000011227417549995295083665533339851

1 commentaire

It is more subtle than you think.
n = vpa(100000000000000000000000000000)
n = 
100000000000000000000000000000.0
vpa(sin(n*pi))
ans = 
0.000000000011227417549995295083665533339851
vpa(sin(n*pi),100)
ans = 
There is a difference.

Connectez-vous pour commenter.

David Hill
David Hill le 21 Juil 2022

0 votes

Use symbolics.
function [out] = isInt(n)
n=sym(n);
out=double(sin(n*pi));
end
Call function
o=isInt('10000000000000000000000000000000000000000000000000000000000000000000');

1 commentaire

Emirhan Solmaz
Emirhan Solmaz le 21 Juil 2022
I tried it but it gives a vector as long as the decimal, which are not "0". I am sorry but didn't get it.

Connectez-vous pour commenter.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by