Just starting out? Need help? Post your questions and find answers here.
ludoke
Enthusiast
Posts: 153 Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)
Post
by ludoke » Fri May 19, 2017 10:42 am
Is there a good solution in pb for avoiding conversion errors from string to double ???
Code: Select all
;testprogram snippet
;purpose milling a circle with depth increment
T_total$="2.00" ;result inputgadget T_total depth
T_increment$="0.20" ;result inputgadget increment depth/pass
increment.d=ValD(T_increment$) ;convert to double
total.d=ValD(T_total$)
new_total.d=0
;Debug increment ;Small conversion error,I suppose this is normal
;Debug total
Repeat
new_total=new_total+increment
Debug new_total
Until new_total>= total
;problem :The loop is run ONCE too much
;So you have To take this into account !!!
;I try the same in BASCOM (basic for microcontroller) and this works well ,I don't know in other programming languages?
;I can work around this problem
;total=Int(total*1000)
;increment=Int(increment*1000) ;this works,is there a better solution in purebasic ??
;Debug total
wilbert
PureBasic Expert
Posts: 3870 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Fri May 19, 2017 11:41 am
You could calculate the number of steps.
Code: Select all
T_total$="2.00" ;result inputgadget T_total depth
T_increment$="0.20" ;result inputgadget increment depth/pass
increment.d=ValD(T_increment$) ;convert to double
total.d=ValD(T_total$)
nSteps.i = total / increment ; number of steps
cStep.i = 0 ; current step
While cStep < nSteps
cStep + 1
Debug total * cStep / nSteps
Wend
Windows (x64)
Raspberry Pi OS (Arm64)
kenmo
Addict
Posts: 1967 Joined: Tue Dec 23, 2003 3:54 am
Post
by kenmo » Fri May 19, 2017 12:48 pm
Problem has nothing to do with the string conversion part, it's the classic "floats can't store most numbers exactly" problem.
Same results in C:
Code: Select all
void main(void) {
printf("%.17f \r\n\r\n", 0.20); // Can't store 1/5 exactly
double increment = 0.20;
double total = 2.00;
double new_total = 0;
do {
new_total += increment;
printf("%.17f \r\n", new_total);
} while (new_total < total);
}
Output:
Code: Select all
0.20000000000000001
0.20000000000000001
0.40000000000000002
0.60000000000000009
0.80000000000000004
1.00000000000000000
1.20000000000000000
1.39999999999999990
1.59999999999999990
1.79999999999999980
1.99999999999999980
2.19999999999999970
Yes, the better methods are, use "fixed point" integers like you said, or divide the interval like Wilbert said.
Marc56us
Addict
Posts: 1477 Joined: Sat Feb 08, 2014 3:26 pm
Post
by Marc56us » Fri May 19, 2017 1:07 pm
Use
Break
Code: Select all
T_total$ = "2.00" ;result inputgadget T_total depth
T_increment$ = "0.20" ;result inputgadget increment depth/pass
increment.d = ValD(T_increment$) ;convert to double
total.d = ValD(T_total$)
new_total.d = 0
Repeat
new_total = new_total + increment
If new_total >= total
Break
EndIf
Debug "" + new_total
Until new_total >= total
Code: Select all
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
Or with new function:
FormatNumber() (PB > 5.50)
Code: Select all
0.20
0.40
0.60
0.80
1.00
1.20
1.40
1.60
1.80
2.00
wilbert
PureBasic Expert
Posts: 3870 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Fri May 19, 2017 1:59 pm
Break still has it's problems.
Try your code with "1.00" or "3.00" for T_total$ and the last step is missing.
Windows (x64)
Raspberry Pi OS (Arm64)