April 29, 2024, 11:45:29 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Testing ..

Started by GWS, November 14, 2005, 03:24:20 AM

Previous topic - Next topic

0 Members and 4 Guests are viewing this topic.

GWS

Hi,

Just started some tests of math functions.ÂÃ,  This code is for the abs() function, and illustrates a few problems:


global sub main()
{
int i,j,k;
float a,b;

/* test of abs()*/

i = -9;
j = abs(i);

writeln(ltrim$(str$(j))+"\n");

writeln("Press any key to close this window\n");
while GetKey() = "";
return 0;
}


Variables i and j are Integer values, so why do we get 9.00 as the result.

Also 'writeln' only handles string parameters.ÂÃ,  Won't there be some way to just 'print' numeric values, or will it always be necessary to use str$() and probably 'using' just to get simple output.

Notice also that inbuilt functions have no identifying color in the editor (while simple strings do).ÂÃ,  It would be nice to be able to highlight functions as 'keywords'.

Oh .. and if we are using the semicolon to terminate lines, could we have comments following it, and hence
; this is a comment ..
That would be better than: /* this is a comment ..*/

best wishes, :)

Graham
Tomorrow may be too late ..

Ionic Wind Support Team

STR$ has an optional parameter which specifies the number of decimal places.

STR$(number, 0);

Paul.
Ionic Wind Support Team

Parker

You couldn't do that kind of comment because something like this is valid in Aurora:
writeln("First line\n"); writeln("Second line\n"); It wouldn't know whether to do a comment or a statement. But you can use the // comment. For example,
writeln("This is some code\n"); // This is a single line comment, like BASIC ' apostrophe.

GWS

Thanx muchely .. :) - pressing on ..

Graham
Tomorrow may be too late ..

GWS

November 14, 2005, 09:48:11 AM #4 Last Edit: November 15, 2005, 02:19:39 AM by GWS
Can't fault abs() ..ÂÃ,  :)

On to acos() which works fine as long as you play fair with it.ÂÃ,  This upsets it:


global sub main()
{
int i,j,k;
double a,b,pi;

// test of acos()

a = -1.1;

writeln(ltrim$(str$(acos(a),15))+"\n");

writeln("Press any key to close this window\n");
while GetKey() = "";
return 0;
}


I don't know what the returned value means ..

acos() is only defined in real numbers for the range (1,0,-1).ÂÃ,  Outside that range the value is complex .. ::)

This raises the old problem of how far to protect the programmer against himself. :o

In this case, probly returning zero might be better. :)ÂÃ,  ÂÃ, The programmer should check that any calculation feeding into acos() should result in a valid number in the range (1,0,-1).ÂÃ, ( Maybe cover valid limits in the user guide .. :) )

Graham

Tomorrow may be too late ..

Ionic Wind Support Team

Graham,
There will be other ways to print in the near future.  'writeln' is there because we needed some way to output 'stuff' to the console/shell without relying on the C library.

Paul.
Ionic Wind Support Team

GWS

Not sure about this one .. again I'm pushing things by asking for a precision of 15 digits from a 'float' calculation ..

global sub main()
{
int i,j,k;
double a,b,pi,d2r,r2d;
float r;

pi = 4*atan(1);
d2r = pi/180;
r2d = 180/pi;

a = 90.0;
r = d2r * a;

writeln(ltrim$(str$(fcos(r),15))+"\n");

writeln("Press any key to close this window\n");
while GetKey() = "";
return 0;
}


Should be 0.0, but we're getting spurious digits after the 7th place of decimals, and it goes negative.

best wishes, :)

Graham
Tomorrow may be too late ..

GWS

Haven't solved the above fcos() problem, but I did manage to get a bit of asm going:

SUB fgcos(num as float),float
{
#asm
fld dword [ebp+8]
fcos
fstp dword [ebp+8]
#endasm
return num;
}


All things are possible ..ÂÃ,  :)

Graham
Tomorrow may be too late ..

Ionic Wind Support Team

Graham,
Which is identical to my fcos function.


global SUB FCOS(num as FLOAT),float
{
#asm
fld dword [ebp+8]
fcos
fstp dword [ebp+8]
#endasm
return num;
}


Floating point precision is only valid to the 7th decimal place.  STR$ accepts a DOUBLE parameter which means the compiler will elevate it to a double precision number before processing.  Even though it still would give strange results.

The math functions are identical to other compilers so I'll have to test the results elsewhere.

Paul.
Ionic Wind Support Team

GWS

November 21, 2005, 02:11:41 AM #9 Last Edit: November 21, 2005, 07:11:50 AM by GWS
Hmm .. tricky .. :)

I seem to remember the 'F' series functions were intended for quick calculations for graphics work .. maybe we need an 'FSTR$' function to take a Float value ..ÂÃ,  ::)

Graham
Tomorrow may be too late ..

Ionic Wind Support Team

The error has nothing to do with STR$ or fcos for that matter.  It has to do with how the math coprocessor handles binary precision.

pi/180 = 0.017453292519943295769236907684886

Your calculation ends up with:

0.017453292519943295

Which is the most a double precision number can handle.

If you wish to work in degrees use the 'd' version of the functions

fcosd(90.0)
cosd(90.0)

Internally fcosd uses a 80 bit representation of pi/180 and loads it directly into the math coprocessor.  For graphics work the difference in calculation is meaningless since we are dealing with less precision on the screen.  Most rotational calculations you'll run across use 0.01745 as a constant.

Paul.
Ionic Wind Support Team

GWS

Phew! .. thanks PaulÂÃ,  :)

So it's just the usual scenario, that you can't believe anything a 'Float' tells you after the seventh place of decimals.

all the best, :)

Graham
Tomorrow may be too late ..

GWS

Just trying out RND with the optional value.

num2 = RAND(10,20) -ÂÃ,  works as expected, but what should

num2 = RAND(20,10) - produce.

I think it just ignores the second parameter in this case .. :)

Not sure what I'd expect, but a program where the two parameters were variables, might come up with the second format under some circumstance.ÂÃ,  I think I'd still want it to generate random values between the two parameters, whichever way round they appeared.ÂÃ,  ::)

Just as num2 = RAND(20,20) , I would expect to give a series of 20.0 values - 'er maybe. :)ÂÃ,  Not very useful I agree.

Graham

Tomorrow may be too late ..

GWS

Been messing about with the SGN(num) function.ÂÃ,  It works like it says on the boxÂÃ,  :) but I'm wondering ...ÂÃ,  ::)

I think there are two functions really.ÂÃ,  The SGN(num) function in Fortran returned 1 if num was zero.
Most everybody else returns 0 as does the existing SGN().

The problem comes if you are modelling a control system say, where the value of some variable is droppng slowly from just above zero, and some control associated with it is open - the value then arrives at zero.ÂÃ,  If it goes below zero, the control is supposed to close.ÂÃ,  But what happens while the value is exactly zero.ÂÃ,  Maybe it doesn't matter, but the valve will close at zero if we are using the SGN() function.ÂÃ,  We'd probably have to program in a tolerance either side of zero to prevent the control from flipping open and closed like a yo-yo at the zero point.

Myself, I think SGN() should return 1 if the sign bit is set, and only return -1 when num is actually negative.

Then there is the Signum function SIGN(num), used in Math, which does return 1,0, or -1 if num is positive,zero, or negative respectively.ÂÃ,  In fact when used with Arrays, it will accept an array parameter, and returns a same-size array with elements set to 1, 0, or -1 depending on whether the input array element is positive,zero,or negative respectively.

Here's a go at implementing them in IBPro, 'cos I'm not very good with Aurora yet .. :)

OPENCONSOLE

def i,j,k:int
def a:double

setprecision 15

a = -1.06
j = 3
k = j * signg(a)

print k

DO
UNTIL INKEY$ <> ""
CLOSECONSOLE
END

SUB SGNg(num as double),int
' Transfer the sign of 'num'.
' SGN() = 1 if num is positive, or -1 if num is zero or negative.
' (Really we are just picking up whether the sign bit is set or not)
def ret as INT
def num2 as double

num2 = -num
IF num2 > num
ret = -1
ELSE
ret = 1
ENDIF

RETURN ret
ENDSUB

SUB SIGNg(num as double),int
' Signum function.
' SIGN() = 1 if num is positive, 0 if num is zero, or -1 if num is negative.
def ret as INT
def num2 as double

num2 = -num
SELECT True
CASE num = 0
ret = 0
CASE num2 > num
ret = -1
DEFAULT
ret = 1
ENDSELECT

RETURN ret
ENDSUB





What do you think? :)

Graham

Tomorrow may be too late ..

Parker

You can always test "if (sgn(x) = 1 or sgn(x) = 0)" if you need that. Or "if (x >= 0)" would be better than using the SGN function.

GWS

Yes, I suppose so .. :)ÂÃ,  I can't remember ever having used it myself.

It just struck me as odd thatÂÃ,  y = v1 * sgn(v2) drops to zero if v2=0, regardless of the value of v1.
Still as long as we know that's what happens.

Graham
Tomorrow may be too late ..

Ionic Wind Support Team

SGN is a pretty standard function in BASIC languages.  -1, 0 or 1.   

Zero is neither negative or positve, that is to say zero doesn't have a sign.  Anything multiplied by zero is of course zero so I don't find it strange at all.

Unless your talking about the math coprocessor where zero can actually have a negative sign.  A flaw in their design that programmers mask out.

Paul.

Ionic Wind Support Team