|
Post by hooshnik on Apr 10, 2018 12:27:29 GMT -5
Using LB 4.04 pro I wrote a program to demonstrate the awkwardness of struct. I am still going to use it for configuration variables because it can give errors for typos in the first 2 dot arguments (plus I don't have to pass a gagillion arguments to sub/funcs which also don't accept the underscore so everything can line up properly). A typo in the third argument is missed by the compiler (which I expected anyway).
' winansi marker é ' version 2 ' tested with LB Pro 4.04: ' proves that structs are global (not in LB 4.04 help), arithmatic is ignored ' silently sometimes (like on overflows). also booleans don't ' seem to be real booleans. I think they are ' type short (2 bytes just like type word) while in LB. using ' len() seems to report the size if converted to a string, not ' the actual size.
global g.myNumber g.myNumber = 3
struct testStruct, _ my.string as char[30], _ a as long, _ b as boolean
testStruct.my.string.struct = "foobar" testStruct.a.struct = 42 testStruct.b.struct = 2
call foo
print input "Hit ENTER to exit ..."; dummy
end
sub foo
testStruct.a.struct = testStruct.a.struct + 1 testStruct.a.struct = testStruct.a.struct + g.myNumber print testStruct.a.struct print "size (string size only) is " ; len(testStruct.a.struct)
testStruct.b.struct = testStruct.b.struct + 256 print testStruct.b.struct ' the next line is ignored by LB! testStruct.b.struct = testStruct.b.struct + 65536 print testStruct.b.struct testStruct.b.struct = testStruct.b.struct + g.myNumber print testStruct.b.struct
' check declarative property of struct ' below not good (undefined struct) 'ttttestStruct.a.struct = 0 ' below not good (key is missing) 'testStruct.adfsss.struct = 0 ' below is good since it looks like a normal variable. testStruct.a.stgerrgruct = 0
' test if statement usage with boolean that is really a short if testStruct.b.struct > 256 then print "testStruct.b.struct " ; testStruct.b.struct ; " is greater than 256" else print "testStruct.b.struct " ; testStruct.b.struct ; " is less than or equal to 256" end if
' check using if with char[] if testStruct.my.string.struct = "foobar" then print "testStruct.my.string.struct is foobar" else print "testStruct.my.string.struct is not foobar" end if end sub
|
|
|
Post by hooshnik on Apr 10, 2018 12:29:15 GMT -5
Also I was wondering is any of this different in LB 4.5.1? I don't have it installed.
|
|
|
Post by hooshnik on Apr 10, 2018 12:38:53 GMT -5
Oh there is another consideration. I have something in my notes here from a while ago. Strings. Using char[] instead of ptr and winstring() wastes a bit more RAM but LB will go faster (unless you painstakingly put the exact length of this string with char[] then no RAM wasted I think) because you arn't using winstring() to convert all the time. All of my assumptions are based on the programmer using struct for more than just API calls.
|
|
|
Post by Brandon Parker on Apr 10, 2018 13:15:34 GMT -5
Well....
Let's first discuss what's just wrong in your test code at a first quick glance ...
The myNumber variable is not set to Global nor is it passed into the Subroutine foo so the value inside the subroutine will be Zero.
The testStruct.a.stgerrgruct actually evaluates to a normal variable in Liberty BASIC so there's nothing actually wrong there.
{:0)
Brandon Parker
|
|
|
Post by hooshnik on Apr 10, 2018 13:31:59 GMT -5
Ok thanks Brandon, you're right. I updated the first post. Just have to watch overflows on variables if the programmer dares to do arithmetic. I also added some if statement tests.
|
|
|
Post by Brandon Parker on Apr 10, 2018 13:34:29 GMT -5
Computers are computers....
It's normally the programmers' responsibility to ensure the data fits within the bounds of variable type defined.
{:0)
Brandon Parker
|
|
|
Post by hooshnik on Apr 10, 2018 14:48:21 GMT -5
I thought it might be a good idea to post my output on windows 10 pro with LB pro 4.04:
46 size (string size only) is 2 258 258 261 testStruct.b.struct 261 is greater than 256 testStruct.my.string.struct is foobar
Hit ENTER to exit ...
|
|
|
Post by hooshnik on Apr 10, 2018 15:13:04 GMT -5
I was never able to use a variable to describe the length of a char. I had to use magic numbers like char[63].
|
|
|
Post by hooshnik on Apr 11, 2018 12:46:34 GMT -5
Just ran this program on type double and got "runtime error float overflow exception". Looks like it's only the integers that are at risk.
struct test, _ a as double
test.a.struct = 0.57823957829752985723895279 for i = 1 to 100 test.a.struct = test.a.struct * i ^ i print test.a.struct next
|
|
|
Post by Brandon Parker on Apr 11, 2018 14:24:05 GMT -5
This is a known "thing". You should only place numbers that are Doubles into Structure elements that are specified as being of type Double. This is one place where LB's automatic number conversion between Int/ Double types gets in the way, but with a little bit of code we can work around that and force Liberty BASIC to create a Double where we want to ensure what is going into the Structure element is actually a Double.
struct test, a As double
test.a.struct = 0.57823957829752985723895279 For i = 1 To 100 test.a.struct = Val(ConvertToDouble$((test.a.struct * i ^ i), 10, 15)) Print test.a.struct Next i
'_____________________________________________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________________________________________
Function ConvertToDouble$(value, sigDig, decDig) sigDig$ = string$("#", sigDig) decDig$ = string$("#", decDig) ConvertToDouble$ = Using(sigDig$;".";decDig$, value) End Function
'_____________________________________________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________________________________________
Function string$(myString$, numstring) For i = 1 To numstring string$ = string$ + myString$ Next i End Function
'_____________________________________________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________________________________________
{:0)
Brandon Parker
|
|
|
Post by hooshnik on Apr 12, 2018 9:15:33 GMT -5
Ok. I didn't understand so I wrote a new test program. I noticed as soon as your code hits scientific notation it returns 0.0 and the program keeps running. I don't like that solution. What if the answer actually was 0.0?
' winansi marker é ' version 1 ' struct double overflow test ' tested with LB Pro 4.04:
struct test, _ a as double
test.a.struct = 0.57823957829752985723895279 for i = 1 to 6 test.a.struct = test.a.struct * i ^ i print test.a.struct next
print "------------------------------"
test.a.struct = 0.57823957829752985723895279 For i = 1 To 6 test.a.struct = Val(ConvertToDouble$((test.a.struct * i ^ i), 10, 15)) Print test.a.struct Next i
print "------------------------------" input "press enter" ; dummy
end
'_____________________________________________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________________________________________
Function ConvertToDouble$(value, sigDig, decDig) sigDig$ = string$("#", sigDig) decDig$ = string$("#", decDig) ConvertToDouble$ = Using(sigDig$;".";decDig$, value) End Function
'_____________________________________________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________________________________________
Function string$(myString$, numstring) For i = 1 To numstring string$ = string$ + myString$ Next i End Function
'_____________________________________________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________________________________________
|
|
|
Post by hooshnik on Apr 12, 2018 9:16:37 GMT -5
output of the last program:
0.57823958 2.31295831 62.4498745 15987.1679 49959899.6 2.33092907e12 ------------------------------ 0.57823958 2.31295831 62.4498745 15987.1679 49959899.6 0.0 ------------------------------ press enter
|
|
|
Post by hooshnik on Apr 12, 2018 9:39:27 GMT -5
Oh I see what you're saying. You're talking in general not just about structs. Well if my software was going to get numbers that high, yeah I'd do checks. I am writing only financial software with dollars and cents so no worries there
|
|
|
Post by Chris Iverson on Apr 12, 2018 10:40:35 GMT -5
Oh I see what you're saying. You're talking in general not just about structs. Well if my software was going to get numbers that high, yeah I'd do checks. I am writing only financial software with dollars and cents so no worries there If that's the case, you're probably better off keeping track of everything as whole-number cents(i.e. use variables of 150 for $1.50, instead of a floating-point of 1.5). Convert to floating-point just before displaying totals to user, but otherwise, always use integer. The reason being is that sometimes floating-point operations result in small errors, but you don't exactly want any errors if you're tracking finances.
|
|
|
Post by hooshnik on Apr 12, 2018 10:40:45 GMT -5
Wrote another test program. Note it fails at 15 and not 16 or 17. That means you can't make a sale bigger than 99 billion bucks without doing something special?
' winansi marker é ' version 1 ' test digits in mantissa vs normal variable and struct double ' tested with LB Pro 4.04:
struct hinum, _ d as double
fraction$ = "01"
for i = 1 to 16 ' seems to fail for me at 15. double rounding error? or too near the end ' of mantissa length (16?). print i ; " digit in mantissa." mantissa$ = mantissa$ + right$(str$(i), 1) ourNumber = val(mantissa$ ; "." ; fraction$) hinum.d.struct = val(mantissa$ ; "." ; fraction$) mantissaRange$ = mantissaRange$ ; "#" print ourNumber print using(mantissaRange$ ; ".##", ourNumber) print hinum.d.struct print using(mantissaRange$ ; ".##", hinum.d.struct) print "---------" next input "press enter" ; dummy$ end
output:
1 digit in mantissa. 1.01 1.01 1.01 1.01 --------- 2 digit in mantissa. 12.01 12.01 12.01 12.01 --------- 3 digit in mantissa. 123.01 123.01 123.01 123.01 --------- 4 digit in mantissa. 1234.01 1234.01 1234.01 1234.01 --------- 5 digit in mantissa. 12345.01 12345.01 12345.01 12345.01 --------- 6 digit in mantissa. 123456.01 123456.01 123456.01 123456.01 --------- 7 digit in mantissa. 1234567.01 1234567.01 1234567.01 1234567.01 --------- 8 digit in mantissa. 12345678.0 12345678.01 12345678.0 12345678.01 --------- 9 digit in mantissa. 1.23456789e8 123456789.01 1.23456789e8 123456789.01 --------- 10 digit in mantissa. 1.23456789e9 1234567890.01 1.23456789e9 1234567890.01 --------- 11 digit in mantissa. 1.23456789e10 12345678901.01 1.23456789e10 12345678901.01 --------- 12 digit in mantissa. 1.23456789e11 123456789012.01 1.23456789e11 123456789012.01 --------- 13 digit in mantissa. 1.23456789e12 1234567890123.01 1.23456789e12 1234567890123.01 --------- 14 digit in mantissa. 1.23456789e13 12345678901234.01 1.23456789e13 12345678901234.01 --------- 15 digit in mantissa. 1.23456789e14 123456789012345.00 1.23456789e14 123456789012345.00 --------- 16 digit in mantissa. 1.23456789e15 1234567890123456.00 1.23456789e15 1234567890123456.00 --------- press enter
|
|