Root(number.f,power.f)

Just starting out? Need help? Post your questions and find answers here.
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Root(number.f,power.f)

Post by Guimauve »

To make my life a little bit more easy to calculate (debug) equation with cubic root I have coded a small Procedure inspirated from Pow() fonction from PB Maths Libraries.

I have tested this small procedure but I would like to have one more test to confirm if it's good or not.

Thanks to the couragous beta tester.

Code: Select all

; Procedure.f Root(number.f, power.f)

; number.f is a number you want to extract the root
; power.f is the type of the root you want
; So if power.f is equal to :
; Value                        Mathematics correspondence
; 2 ----------------------> Square Root  -----> Not important we have Sqr(number.f)
; 3 ----------------------> Cubic Root -----> Important for me
; 4 ----------------------> 4th Root
; 5 ----------------------> 5th Root
; 6 ----------------------> 6th Root
; X ----------------------> Xth Root

; **************************************
;  WARNING VALUE CAN'T BE EQUAL TO 0
; ***************************************

Procedure.f Root(number.f,power.f)
     
     results.f = Pow(number, (1 / power))
     
     ProcedureReturn results.f
     
EndProcedure
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

Guimauve:
I get results bigger than the expected. :cry:

Code: Select all

Procedure.f Root(number.f,power.f) 
  ProcedureReturn Pow(number, (1 / power)) 
EndProcedure 
a= 13*13*13
Debug a
Debug root(a,3)
stan
User
User
Posts: 29
Joined: Tue Jun 10, 2003 2:46 pm

Post by stan »

Guimauve,

Thre is nothing wrong about your procedure, but telling if it works well or not depends on the accuracy you expect, here is a slightly modified version of your code which can help you to see if ir fits your needs.

Code: Select all

OpenConsole( )

Procedure.f Root(number.f,power.f) 
     ProcedureReturn Pow(number, (1/power) )       
EndProcedure

start = Date( )
proof$ = "YES"

; Change values to check against your needs (as is it will tell you it
; does not work, but if you lower delta_max to say 0.1 it works ...)
;

delta_max.f = 0.001
max_power = 20
max_number = 10000

For j = 1 To max_power
  pow.f = j ;
  For i = 1 To max_number
    f.f = i
    k.f = Root( f, pow)
    l.f = Pow( k, pow )
    If Abs( l - f ) > Delta_max
      PrintN( StrF( l ) + " " + StrF( f ) )
      proof$ = "NO"
      Input( ) ; This is just to let you read the output
    Endif  
  Next i
Next j

stop = Date( ) - start ;

PrintN( "Elapsed Time = " + Str( stop ) + " Max_number = " + Str( max_number ) + " Max_power = " + Str( max_power )  +" Proved = " + proof$ ) 

Input( ) ; This is just to let you read the output

CloseConsole( )
Hope this helps.

Bests.

Stan.
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

Sorry but my test are OK.

Try this code :

Code: Select all

;- Dimension de la fenetre principale
#LargeurFenetre = 500
#HauteurFenetre = 250

Enumeration
     #Text_gadget01
     #Text_gadget02
     #Text_gadget03
     #Text_gadget04
     #String_gadget01
     #String_gadget02
     #Button_start
     #Frame3D_root_fonction
     #Frame3D_pow_fonction
EndEnumeration

Declare.f Root(number.f, power.f)

Global number_to_caculate.f, the_power.f

; Création de la fenètre principale
If OpenWindow(0, 200, 100, #LargeurFenetre, #HauteurFenetre, #PB_Window_MinimizeGadget | #PB_Window_SizeGadget, "Root Fonction test")
     
     If CreateGadgetList(WindowID())
          TextGadget(#Text_gadget01, 5, 10, 500 / 2 - 10, 17, "Number")
          StringGadget(#String_gadget01, 5, 30, 500 / 2 - 10, 18, "")
          
          TextGadget(#Text_gadget01, 5, 50, 500 / 2 - 10, 17, "Power")
          StringGadget(#String_gadget02, 5, 70, 500 / 2 - 10, 18, "")
          
          ButtonGadget(#Button_start, 5, 100, 500 / 2 - 10, 24, "Verify")
          
          Frame3DGadget(#Frame3D_root_fonction, 5, 145, 245, 100, "Root(number.f,power.f)")
          TextGadget(#Text_gadget03, 15, 160, 500 / 2 - 50, 24, "", #PB_Text_Border | #PB_Text_center )
          
          Frame3DGadget(#Frame3D_pow_fonction, 250, 145, 245, 100, "Pow(number.f,1/power.f)")
          TextGadget(#Text_gadget04, 260, 160, 500 / 2 - 50, 24, "", #PB_Text_Border | #PB_Text_center )
     EndIf
     
EndIf

; ************************************************************************************************************************



Repeat
     EventID = WaitWindowEvent()
     
     If EventID = #PB_EventGadget
          Select EventGadgetID()
               Case #Button_start
                    number_to_caculate = ValF(GetGadgetText(#String_gadget01))
                    the_power = ValF(GetGadgetText(#String_gadget02))
                    
                    SetGadgetText(#Text_gadget03, StrF(Root(number_to_caculate, the_power), 6))
                    SetGadgetText(#Text_gadget04, StrF(Pow(number_to_caculate, 1/the_power), 6))
                    
                    
          EndSelect
     EndIf
Until EventID = #PB_EventCloseWindow
End

Procedure.f Root(nombre.f, puissance.f)
     
     resultat.f = Pow(nombre, (1 / puissance.f))
     
     ProcedureReturn resultat.f
     
EndProcedure
Sorry but this one is my french Version.

Some value to test

Number = 125
Power = 3
Results = 5.000000

Number = 27
Power = 3
Results = 3.000000

Number = 64
Power = 3
Results = 4.000000

Number = 25
Power = 2
Results = 5.000000

Number = 8
Power = 3
Results = 2.000000

Regards
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

Guimauve:

Float error :?:
Try 91125 power 3 (=45*45*45)
Result=45.000004
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

Yes know that you can try 1000 power 3 and you will have 10.000001.
I think I need to use a double type of value for calculation.

But If you check carefully the procedure , Cubic Root is egal to Power (1/3). So if you need to calculate a cubic root you will have an errors.

Also my "Root" procedure re-use the "Pow" fonction. In the end the results are the same. It's Floaf value limits.

I will try it with F64 Libraries coded by freedimension.

Thanks to all of you.

Guimauve
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

Good luck, and please, tell us when you found the solution!
Regards
Einander
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

Digit precision = Cubic root of 1000
"Conversion with StrF() command"

5 = 10.00000
6 = 10.000001
7 = 10.0000010
8 = 10.00000095
9 = 10.000000954

In the French help file I can read this about StrF() :

Le nombre n'est pas arrondi, mais coupé.

Translation :

The number will be not rounded, but turncated.

In PB news about V3.70

Fixed: StrF(): if a digit number is specifed it rounds correctly

Ok the problem is here.

According to the cubic root of 1000 the float precision is good for the 6th digits. To remove the rounds effex I need to convert the float value with 10 digits, start a FindString command on this string for the (.), count 6 caracters from the (.) position, and finally trim the string to have a number like : 10.000000

Or ask Fred or anyone else to add 2 options to the StrF() command

1st -- #PB_STRF_ROUND_LAST_DIGIT ----> This one is the only and the current option.

2nd -- #PB_STRF_CUT_LAST_DIGIT ----> A new option to cut the float number directly after the specified precision.

Ex. variable = 10.000000954...

StrF(variable.f,6,#PB_STRF_CUT_LAST_DIGIT)

The results = 10.000000

It's just a suggestion. I can code a small procedure for me but I think this feature can be very useful for several PB Coder.

Best Regards
stan
User
User
Posts: 29
Joined: Tue Jun 10, 2003 2:46 pm

Post by stan »

Hi,

Sure it works ... because you just wrote the same thing (in disguise) twice :

Root(number_to_caculate, the_power) == pow(number_to_caculate, 1/the_power)

as you defined
root( x, y ) = pow( x, 1/y ) ...

but if you try pow( root( x, y ), y ) you should get x, which is not the case try this code : (yours slighly modified to display pow(root(x,y),y) :

Code: Select all

;- Dimension de la fenetre principale 
#LargeurFenetre = 500 
#HauteurFenetre = 250 

Enumeration 
     #Text_gadget01 
     #Text_gadget02 
     #Text_gadget03 
     #Text_gadget04 
     #String_gadget01 
     #String_gadget02 
     #Button_start 
     #Frame3D_root_fonction 
     #Frame3D_pow_fonction 
EndEnumeration 

Declare.f Root(number.f, power.f) 

Global number_to_caculate.f, the_power.f 

; Création de la fenètre principale 
If OpenWindow(0, 200, 100, #LargeurFenetre, #HauteurFenetre, #PB_Window_MinimizeGadget | #PB_Window_SizeGadget, "Root Fonction test") 
      
     If CreateGadgetList(WindowID()) 
          TextGadget(#Text_gadget01, 5, 10, 500 / 2 - 10, 17, "Number") 
          StringGadget(#String_gadget01, 5, 30, 500 / 2 - 10, 18, "") 
          
          TextGadget(#Text_gadget01, 5, 50, 500 / 2 - 10, 17, "Power") 
          StringGadget(#String_gadget02, 5, 70, 500 / 2 - 10, 18, "") 
          
          ButtonGadget(#Button_start, 5, 100, 500 / 2 - 10, 24, "Verify") 
          
          Frame3DGadget(#Frame3D_root_fonction, 5, 145, 245, 100, "Root(number.f,power.f)") 
          TextGadget(#Text_gadget03, 15, 160, 500 / 2 - 50, 24, "", #PB_Text_Border | #PB_Text_center ) 
          
          Frame3DGadget(#Frame3D_pow_fonction, 250, 145, 245, 100, "Pow(number.f,1/power.f)") 
          TextGadget(#Text_gadget04, 260, 160, 500 / 2 - 50, 24, "", #PB_Text_Border | #PB_Text_center ) 
     EndIf 
      
EndIf 

; ************************************************************************************************************************ 



Repeat 
     EventID = WaitWindowEvent() 
      
     If EventID = #PB_EventGadget 
          Select EventGadgetID() 
               Case #Button_start 
                    number_to_caculate = ValF(GetGadgetText(#String_gadget01)) 
                    the_power = ValF(GetGadgetText(#String_gadget02)) 

; ******************** MODIFIED PART *************                    
                    SetGadgetText(#Text_gadget03, StrF(Pow(Root(number_to_caculate, the_power), the_power), 6)) 
                    SetGadgetText(#Text_gadget04, StrF(pow(Pow(number_to_caculate, 1/the_power), the_power), 6)) 
; ***************** END OF MODIFIED PART ***********
                    
          EndSelect 
     EndIf 
Until EventID = #PB_EventCloseWindow 
End 

Procedure.f Root(nombre.f, puissance.f) 
      
     resultat.f = Pow(nombre, (1 / puissance.f)) 
      
     ProcedureReturn resultat.f 
      
EndProcedure
You'll get the same results in both text gadget which is different from the input number ( try number 100 and pow 4 or 5 for instance ).

Your code is right, but rounding errors cause the problem.

Bests.

Stan.
Post Reply