Page 1 of 1

math problems

Posted: Fri May 19, 2017 10:42 am
by ludoke
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

Re: math problems

Posted: Fri May 19, 2017 11:41 am
by wilbert
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

Re: math problems

Posted: Fri May 19, 2017 12:48 pm
by kenmo
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.

Re: math problems

Posted: Fri May 19, 2017 1:07 pm
by Marc56us
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
:idea:

Code: Select all

Debug "" + new_total  
:arrow:

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

Debug FormatNumber(new_total, 2)
:arrow:

Code: Select all

0.20
0.40
0.60
0.80
1.00
1.20
1.40
1.60
1.80
2.00
:wink:

Re: math problems

Posted: Fri May 19, 2017 1:59 pm
by wilbert
Marc56us wrote:Use Break
Break still has it's problems.
Try your code with "1.00" or "3.00" for T_total$ and the last step is missing.