westaust55
Moderator
As a follow on the my past calculation of a square root for values (0 - 65535) to two decimal places, I have prepared a similar piece of PICAXE BASIC code to calculate the cube root of a value (0 to 65535) to two decimal places.
I stopped at two decimal places as the maths is at 2 decimnal places already using 32-bit numbers with intermediate math values up to 100 million and for a thord decimal place
These values could be as high as 10,000 million which exceeds the capacity of a 32-bit value.
The 2 decimal place format and result multiplied by 100 is in keeping with the PICAXE inbuilt SIN and COS functions.
Due to the 32-bit maths, the code does utilise virtually every byte/word variable for the X1 and M2 part.
Therefore when used as part of a larger program it will be necessary to save all the byte vairbale b0 to b27 to RAM before performing this routine and having just the oriignal value in word variable "X".
Below is the PICAXE BASIC routine for calculating a cube root of an integer number from 0 to 65535 to 2 decimal places.
The code can no doubt be compressed, but left as posted so that others may be able to understand how it functions.
As posted it occupies 312 bytes of program space.
EDIT:
A couple of other math functions I have provided code for back in 2011 are as follows:
Square Root to two decimal places: http://www.picaxeforum.co.uk/showthread.php?19714-Calculate-Square-Root-to-two-decimal-places
Log (base 10) to two decimal places: http://www.picaxeforum.co.uk/showthread.php?19695-Calculate-Logarithms-with-PICAXE-math
Note that you can use a constant factor to convert from Log to Ln (natural log - base e).
I stopped at two decimal places as the maths is at 2 decimnal places already using 32-bit numbers with intermediate math values up to 100 million and for a thord decimal place
These values could be as high as 10,000 million which exceeds the capacity of a 32-bit value.
The 2 decimal place format and result multiplied by 100 is in keeping with the PICAXE inbuilt SIN and COS functions.
Due to the 32-bit maths, the code does utilise virtually every byte/word variable for the X1 and M2 part.
Therefore when used as part of a larger program it will be necessary to save all the byte vairbale b0 to b27 to RAM before performing this routine and having just the oriignal value in word variable "X".
Below is the PICAXE BASIC routine for calculating a cube root of an integer number from 0 to 65535 to 2 decimal places.
The code can no doubt be compressed, but left as posted so that others may be able to understand how it functions.
As posted it occupies 312 bytes of program space.
Code:
; Calculate cube root of an integer number from 0 to 65535
;
; The result is a value to 2 decimal places multiplied by 100
;
; Thus:
; CuRt (2) = 1.25992 and is given as 125
; CuRt (100) = 4.64158 and is given as 464
; CuRt (1000) = 10.00000 and is given as 1000
; CuRt (21000) = 27.58924 and is given as 2758
; CuRt (43210) = 35.09092 and is given as 3509
; CuRt (65535) = 40.31727 and is given as 4031
; The routine is based on the hand calculation methods
; described on various internet sources such as:
; http://www.mathpath.org/Algor/cuberoot/algor.cube.root.htm
;
;
;
; Picaxe program routine created by
; Westaust55 (Perth, Western Australia)
;
;
; Date: 10 March 2013
; Rev: 0
;
#PICAXE 40X1
#NO_DATA
#NO_TABLE
SYMBOL ThisDig = b1
SYMBOL x = w2
SYMBOL Thousands = w3 ; Holds the thousands part of the enter value (if > 999)
SYMBOL ThouModul = w4 ; Hold the units, tens, hundreds digits
SYMBOL HighRemdr = w5 ; High word of a 32 bit value as remainder during calcs
SYMBOL LowRemdr = w6 ; Low word of a 32 bit value as remainder during calcs
SYMBOL HighVal = w7 ; High word of a 32 bit value during calcs for next digit
SYMBOL LowVal = w8 ; Low word of a 32 bit value during calcs for next digit
SYMBOL HighValHold= w9
SYMBOL LowValHold = w10
SYMBOL InterVal = w11
SYMBOL Result = w12 ; Word variable wher the cube root to 2 decimal places is built up
SYMBOL Digit = b26 ; Used as index for FOR...NEXT loop in main program
SYMBOL Value = b27 ; Used as index for FOR...NEXT loop in subroutine
; start of the program example
Main:
; Entry of a value
DataEntry:
SERTXD ("Input a value (0 to 65535): ", cr,lf)
SERTXD ("Enter in quotes", cr,lf)
SERRXD [65000], #x ; early 40X1 parts Must have the timeout - PE tells you so!
SERTXD (cr,lf,"Entered Value: ", #x, cr,lf)
Thousands = x / 1000 ; extract the thousands part as a value
ThouModul = x // 1000 ; extract the hundreds, tens, units part as a value
HighRemdr = 0
LowRemdr = Thousands
Result = 0 ; Clear the result
FOR Digit = 0 to 3
GOSUB FindThisDigit ; Find the next digit that matches the cube root
Result = Result * 10 + ThisDig ; advance the remainder along one digit and add in the new units digit
Thousands = LowRemdr ; use 'thousands' value as no longer required
LowRemdr = LowRemdr - LowValHold
IF LowRemdr > Thousands THEN ; test for underflow down through zero to new higher value
DEC HighRemdr ; if there was underflow then adjust the high word of 32-bit value
ENDIF
InterVal = LowRemdr ** 1000 ; we need to multiply by 1000 - determine what overflow form low word to high word
LowRemdr = LowRemdr * 1000 ; determine the remainder within the low word of 32-bit value
HighRemdr = HighRemdr - HighValHold * 1000 + InterVal ; then adjust the high word of 32 bit value
Thousands = LowRemdr ; hold the low word of remainder for overflow test
IF Digit = 0 THEN ; if completing the first digit then there may be a modulus 1000 value from original value to add in
LowRemdr = LowRemdr + ThouModul ;Add in the modulus 1000 part from orignal value
IF LowRemdr < Thousands THEN ; if there is overflow
INC HighRemdr ; thena djust the high word of 32-bit remiander
ENDIF
ENDIF
NEXT Digit ; return for next digit until up to 2 decimal places are done
Finalise:
SERTXD ("Cube Root = ", #Result, cr, lf)
GOTO Main
;
; ===== Subroutine to determine the value for the next digit
FindThisDigit:
ThisDig = 0
HighValHold = 0
LowValHold = 0
FOR Value = 1 to 9 ; result for Value= 0 is always 0, so start at 1
InterVal = Result * 10 + Value * Value
LowVal = 30 * Result ; a temporary intermediate use of LowVal variable
HighVal = LowVal ** InterVal ; determine the upper word of the 32 bit value
LowVal = LowVal * InterVal ; determine the lower word of the 32 bit value
InterVal = Value * Value * Value ; Last part of equation to add into 32-bit value
thousands = LowVal ; use 'thousands' value as no longer required
LowVal = LowVal + Interval ; add last part into lower word of 32-bit number
IF LowVal < thousands THEN ; test if roll over occurred due to addition
INC HighVal ; if so, then adjust high word of 32 bit number
ENDIF
IF HighVal > HighRemdr THEN Exit ; This digit value is TooHigh
IF HighVal = HighRemdr AND LowVal > LowRemdr THEN EXIT ; This digit value is TooHigh
ThisDig = Value ; this digit value would be okay, so save the digit value
HighValHold = HighVal ; the the resultant 32-bit value to deduct from remainder
LowValHold = LowVal
NEXT Value
RETURN
; ============================================================
A couple of other math functions I have provided code for back in 2011 are as follows:
Square Root to two decimal places: http://www.picaxeforum.co.uk/showthread.php?19714-Calculate-Square-Root-to-two-decimal-places
Log (base 10) to two decimal places: http://www.picaxeforum.co.uk/showthread.php?19695-Calculate-Logarithms-with-PICAXE-math
Note that you can use a constant factor to convert from Log to Ln (natural log - base e).
Last edited: