|
Post by Brandon Parker on Apr 12, 2018 10:50:23 GMT -5
Yeah, you need to understand what data you are dealing with. The ConvertToDouble$() Function works perfectly fine; you did not change the integer portion of the number you told the function to convert. I know the terminology isn't correct for what the parts of the number are, but it works and I wrote the function some time ago. No need to change it for me in that case.
To get the function to return higher numbers properly just increase the size that it is allowed to return.
Change the line below from this:
test.a.struct = Val(ConvertToDouble$((test.a.struct * i ^ i), 10, 15))
To this:
test.a.struct = Val(ConvertToDouble$((test.a.struct * i ^ i), 100, 15))
You could even make the 100 a smaller value if you wanted; whatever works best...
Here is the output from your code a few posts ago with the change I show above.
{:0)
Brandon Parker
|
|
|
Post by hooshnik on Apr 12, 2018 10:57:15 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. Are you saying that Liberty basic doesn't do this automatically for normal variables? I thought it did.
|
|
|
Post by Brandon Parker on Apr 12, 2018 11:02:01 GMT -5
What Chris is saying is that if you are performing lots of calculations on dollar/ cents then you are better off performing all of the calculation as if there are no dollars; ONLY pennies. So... $1.50 would be 150 pennies.... Due to 1.5 being a floating point and Liberty BASIC's reliance on the processor's floating point math abilities that $1.50 might actually display as $1.499999999 or something like that. When you deal with just the integer values for the pennies and then just divide the displayed result by 100 when you want to show the user the value will tend to be "more accurate" as you will not have the floating point math issues involved for the most part.
{:0)
Brandon Parker
|
|
|
Post by hooshnik on Apr 12, 2018 11:08:58 GMT -5
Brandon is this the double rounding error problem?
|
|
|
Post by hooshnik on Apr 12, 2018 11:16:04 GMT -5
If a tax rate is 0.09975 then I have to keep the integers even higher like times 10000. What a bother. It's only 40,000 lines of code
|
|
|
Post by hooshnik on Apr 12, 2018 11:19:26 GMT -5
There is another consideration. If I sell only in Canada I should be ok right? There is no penny here anymore. Everything is rounded to the nearest 5c.
|
|
|
Post by Brandon Parker on Apr 12, 2018 12:15:58 GMT -5
There is another consideration. If I sell only in Canada I should be ok right? There is no penny here anymore. Everything is rounded to the nearest 5c. Sorry to hear that.... People are always pointing out the uselessness of pennies and I poke that right back them. Without pennies everything increases by at minimum 5 cents; what a pain... {:0) Brandon Parker
|
|
|
Post by hooshnik on Apr 12, 2018 15:51:45 GMT -5
|
|
|
Post by tsh73 on Apr 12, 2018 17:12:39 GMT -5
|
|
|
Post by tsh73 on Apr 12, 2018 17:19:32 GMT -5
Second point. 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 So last number printed is 1.16229468e287 It would be multiplied by (i+1) ^( i+1) that is 2.0880468e31 That gives us SOME_NUMBERe318 But there is a limit on DOUBLE 1.79769313486231D+308 So you get what you really deserve - "float overflow exception". Now tell me what was the point of ConvertToDouble$() function?
|
|
|
Post by Brandon Parker on Apr 12, 2018 21:53:22 GMT -5
Anatoly, The ConvertToDouble$() function can be used to force LB to make an Integer a Double when insertion into a Struct Double variable occurs. Since one can never be sure for some calculations what the number will be it might be 2.25, 3.86, or 1.0. In the last case Liberty BASIC will fail to properly insert the number into a Struct variable whose type has been set to Double because Liberty BASIC will automatically truncate the mantissa and convert 1.0 to the Integer value of 1. When the code then attempts to insert a 1 into a Double it fails.
By using the ConvertToDouble$() function as shown in the fictitious code below Liberty BASIC will take a calculated value that would result in an Integer and make it a Double.
No one ever said it will always work or anyone should ever use the function. The programmer must always be aware of what data they are storing into which type. This function works for me and my application because I use it responsibly; knowing what I'm putting into each variable within a set range.
'Fictitious Code Struct myStruct, value As Double
myVar = some calculation resulting in 1.0 'LB will make this a 1 (Int)
myStruct.value.struct = Val(ConvertToDouble$(myVar, 10, 15)) 'Using the code invoked here LB will take that 1 (Int) and push a 1.0 (Double) into the Struct 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
'_____________________________________________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________________________________________
{:0)
Brandon Parker
|
|
|
Post by tsh73 on Apr 13, 2018 1:50:11 GMT -5
Brandon, few problems. First, hooshnik didn't actually have problems with integer passed as double. His error cites numeric overflow, that is, passing over Double limits (10^308). (I tried pass integer as Double - LB 4.04 just crashes with register dump in error.log with a message Message 1001: a non-continuable protection violation has occurred. Check ERROR.LOG file. )
Second, ConvertToDouble$(myVar, 10, 15) returns 0.0 for myVar>10^11 Since you using it withing limits it works for you - but for him it makes wrong results.
Now it doesn't matter but if ConvertToDouble$ didn't return incorrect 0.0 for big number, number would grow over 1e308 And USING (in ConvertToDouble$) fails then (looks like big integer is converted to DOUBLE by USING) Exactly with Runtime error: Float overflow exception
Last thing. I think I've seen somewhere way of converting INT to DOUBLE by multiplying to (1+1e-16)
Struct myStruct, value As Double
myVar = 1 'integer
for i = 1 to 400 myVar = myVar*10 'myStruct.value.struct = myVar 'fails myStruct.value.struct = myVar*(1+1e-16) 'works print i, myVar, myStruct.value.struct next End
|
|
|
Post by hooshnik on Apr 13, 2018 7:43:19 GMT -5
'myStruct.value.struct = myVar 'fails
Holy crap! My eyes almost popped out of my head when I saw this. Sure enough LB will kill the program and itself. I thought LB was casting the RHS properly the whole time!
|
|
|
Post by Brandon Parker on Apr 13, 2018 7:47:58 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 This is the part that I was focusing on....not get the automatically converted value (integer) into a Double struct element. As I said before Anatoly, the PROGRAMMER must ALWAYS know what data he/ she is dealing with and where he/ she is placing that data. It is POOR practice to not understand this principle. Another benefit of using the function other it forcing Int's into Double's is formatting. In my situation I can't just allow LB to spit out 15 digits of precision and let that be displayed. I find the function useful; if others do not then they are not required to use it, including you. {:0) Brandon Parker
|
|