Post Reply 
Getting 'N/D' to eval as a fraction not a decimal
03-05-2015, 07:57 AM
Post: #1
Getting 'N/D' to eval as a fraction not a decimal
In a program, I want to generate a fraction e.g.
N:=1 ; D:=2; RETURN 'N/D';

I've tried the following:
Code:
PRINT('N/D');             => N/D
PRINT(EVAL('N/D');        => 0.5
PRINT(CAS.exact('N/D'));  => N/D
PRINT(CAS.exact(N/D));    => 1/2
Clearly, the last one does what I want but it seems a bit wasteful to have to convert N/D to a decimal fraction and then convert it back again to a proper fraction (if I've understood the exact() function correctly).

Am I missing something here? Surely there must be a simpler way that builds the fraction directly?
Find all posts by this user
Quote this message in a reply
03-06-2015, 03:50 AM
Post: #2
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-05-2015 07:57 AM)BruceH Wrote:  In a program, I want to generate a fraction e.g.
N:=1 ; D:=2; RETURN 'N/D';

The following works in Home programs IF both N and D are integers AND you make sure that the "Change apparent integers into exact integers" setting in CAS Settings (page 1, check box at end of line 3) is checked:

print(simplify(N/D))

An elegant solution that always works (and doesn't rely on non-programmable CAS settings) would be greatly appreciated.

<0|ɸ|0>
-Joe-
Visit this user's website Find all posts by this user
Quote this message in a reply
03-06-2015, 08:32 PM
Post: #3
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-06-2015 03:50 AM)Joe Horn Wrote:  An elegant solution that always works (and doesn't rely on non-programmable CAS settings) would be greatly appreciated.

Well, I found a solution that (I think) always works, but it sure ain't elegant!

subst(N/D,N=N,D=D); gives '1/2'
Find all posts by this user
Quote this message in a reply
03-07-2015, 01:48 AM (This post was last modified: 03-07-2015 02:02 AM by Joe Horn.)
Post: #4
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-06-2015 08:32 PM)BruceH Wrote:  Well, I found a solution that (I think) always works, but it sure ain't elegant!

subst(N/D,N=N,D=D); gives '1/2'

Unfortunately that returns a single decimal fraction (not a ratio of two integers) if the non-programmable "Change apparent integers into exact integers" setting in CAS Settings (page 1, check box at end of line 3) is unchecked. Sad

EDIT: Very non-elegant, but this works:

print(string(N)+"/"+string(D))

EDIT 2: Do NOT use the following method unless both N and D are always very small integers. If either N or D are large, it is prone to error, and it depends on the value of the system variable epsilon (CAS Settings, page 2):

print(exact(N/D))

<0|ɸ|0>
-Joe-
Visit this user's website Find all posts by this user
Quote this message in a reply
03-07-2015, 06:31 AM
Post: #5
RE: Getting 'N/D' to eval as a fraction not a decimal
What about CAS.eval(N/D) ?

(How large do N & D need to be before you start seeing the errors you refer to?)
Find all posts by this user
Quote this message in a reply
03-09-2015, 02:21 AM
Post: #6
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-07-2015 06:31 AM)BruceH Wrote:  What about CAS.eval(N/D) ?

As we've seen several times in this discussion, that fails when the non-programmable "Change apparent integers into exact integers" setting in CAS Settings (page 1, check box at end of line 3) is unchecked.

OOH OOH... I found one:

CAS(IP(N)/IP(D))

in Home always returns a fraction, regardless of the "change apparent integers" CAS setting.

<0|ɸ|0>
-Joe-
Visit this user's website Find all posts by this user
Quote this message in a reply
03-09-2015, 10:21 PM
Post: #7
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-09-2015 02:21 AM)Joe Horn Wrote:  
(03-07-2015 06:31 AM)BruceH Wrote:  What about CAS.eval(N/D) ?

As we've seen several times in this discussion, that fails when the non-programmable "Change apparent integers into exact integers" setting in CAS Settings (page 1, check box at end of line 3) is unchecked.

OOH OOH... I found one:

CAS(IP(N)/IP(D))

in Home always returns a fraction, regardless of the "change apparent integers" CAS setting.
Thanks Joe, I'll use that.

Can you give some examples of numbers that fail? I'd like to turn this into an article.
Find all posts by this user
Quote this message in a reply
03-10-2015, 03:46 AM
Post: #8
RE: Getting 'N/D' to eval as a fraction not a decimal
I would probably use the same approach as in the QPI program:

frac:="'" + N + "/" + D + "'";
expr(frac);

In home view an exact fraction is a symbolic object much like that of the HP48 series. You can manually type in such fractions using the tic marks. The code snippet just mimics that.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
03-10-2015, 04:24 AM
Post: #9
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-09-2015 10:21 PM)BruceH Wrote:  Can you give some examples of numbers that fail? I'd like to turn this into an article.

There are several failures going on here, so here's a description of them all.

If N=23 and D=45, then all of the following (copied from the above discussion) return 0.51111111111 in Home instead of 23/45 *if* the non-programmable "Change apparent integers into exact integers" setting in CAS Settings (page 1, check box at end of line 3) is unchecked:

EVAL('N/D')
CAS.eval(N/D)
simplify(N/D)
subst(N/D,N=N,D=D)

If N=1234567, and D=3456789, then the following returns the wrong fraction in Home if epsilon (CAS Settings, page 2) is the default value (1E-12):

exact(N/D) --> 176366/493825 (should be 1234567/3456789)

The above can be "fixed" by making epsilon smaller (e.g. 1E-13 in this case), but then larger values of N and D will fail. For example, exact(12345678/23456789) is wrong when epsilon is 1E-13. Due to a very unfortunate CAS limitation, values of epsilon smaller than 1E-15 are all treated as 1E-15 by the "exact" function, so exact(N/D) is usually wrong when N and D are very large. For example, exact(12345678/23456789) is wrong no matter what epsilon is, even 1E-15 or smaller.

The solution to the original problem is to use functions that force the inputs (N and D) to be CAS-type integers, regardless of any mode settings. There are several functions that do this, such as IP. That's why CAS(IP(N)/IP(D)) works; the IP's turn the Home values of N and D into CAS-type integers, then CAS divides them and returns the fraction back to Home.

Annoying factoid: In CAS (not in Home), if the "Change apparent integer" flag is clear, then the IP function only turns the number into an integer if it's spelled in uppercase. Luckily, CAS(IP()) always sends IP to CAS in uppercase, no matter how the user spells it, so CAS(ip()) works in Home, and no matter what the CAS settings are. But CAS("ip(N)/ip(D)") fails, because "ip" got passed to CAS as-is (because it's in a string), and didn't get upper-cased.

<0|ɸ|0>
-Joe-
Visit this user's website Find all posts by this user
Quote this message in a reply
03-10-2015, 06:26 AM
Post: #10
RE: Getting 'N/D' to eval as a fraction not a decimal
Hello,

the subst solution is indeed the 'proper' one as it represents what you are really trying to acheive, replace N and D in the N/D expression by their values. Even if the syntax can look strange and confusing...

The string solution EXPR(N+"/"+D) is much less confusing, but most likely slower...

All the approaches using the CAS will be slower..

Cyrille
Find all posts by this user
Quote this message in a reply
03-11-2015, 04:23 AM
Post: #11
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-10-2015 06:26 AM)cyrille de brébisson Wrote:  the subst solution is indeed the 'proper' one ...

... but not useable in a program, since it depends on the setting of a non-programmable mode (as explained above).

(03-10-2015 06:26 AM)cyrille de brébisson Wrote:  All the approaches using the CAS will be slower..

TEVAL(CAS(IP(N)/IP(D))) --> 0.001_s on an A/6975 Prime. TEVAL cannot yield any briefer non-zero duration.

<0|ɸ|0>
-Joe-
Visit this user's website Find all posts by this user
Quote this message in a reply
03-11-2015, 06:18 AM
Post: #12
RE: Getting 'N/D' to eval as a fraction not a decimal
ho, sorry, when I saw subst, I assumed that the where command was implied. The where command was meant...

Try 'N/D'|{N=N,D=D} I think that it will work, regardless of the settings as it stays in numeric mode.

Cyrille
Find all posts by this user
Quote this message in a reply
03-11-2015, 06:23 PM
Post: #13
RE: Getting 'N/D' to eval as a fraction not a decimal
(03-11-2015 06:18 AM)cyrille de brébisson Wrote:  Try 'N/D'|{N=N,D=D} I think that it will work, regardless of the settings as it stays in numeric mode.

That doesn't work on Prime rev 6975. It merely returns N/D as such, without changing the variables' names into their values.

<0|ɸ|0>
-Joe-
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 2 Guest(s)