13
\$\begingroup\$

The goal of this code golf is to create a program or function that calculates and outputs the cube root of a number that's given as input.
The rules:

  • No external resources
  • No use of built-in cube root functions.
  • No use of methods/operators that can raise a number to a power (that includes square root, 4th root, etc.).
  • Your function/program must be able to accept floating-point numbers and negative numbers as input.
  • If the cube root is a floating-point number, then round it to 4 numbers after the decimal point.
  • This is a code golf, the shortest code in bytes wins.

Test cases:

27 --> 3
64 --> 4
1  --> 1
18.609625 --> 2.65
3652264 --> 154
0.001 --> 0.1
7  --> 1.9129

You can use all test cases above to test negative numbers (-27 --> -3, -64 --> -4 ...)

\$\endgroup\$
8
  • \$\begingroup\$ damn, if you allowed only numbers with precise cube, I would have a nice golf \$\endgroup\$
    – yo'
    Feb 22, 2014 at 12:51
  • 1
    \$\begingroup\$ Judging from your test cases I assume the program only needs to deal with real numbers? \$\endgroup\$
    – user12205
    Feb 22, 2014 at 12:57
  • \$\begingroup\$ @ace add complex and I change 2 letters in my code ;) \$\endgroup\$
    – yo'
    Feb 22, 2014 at 13:05
  • 2
    \$\begingroup\$ Is rounding to 4 digits after the decimal point a strong requirement? Or could it be something like "you aren't required to show more than 4 digits after the decimal point"? \$\endgroup\$ Feb 22, 2014 at 15:15
  • 1
    \$\begingroup\$ With reference to my answer using Exp(ln(x)/3) (and several clones of it) please clarify if Exp is allowed. I assume pow(x,1/3) is not (even though it is technically not a cube root function.) \$\endgroup\$ Feb 23, 2014 at 2:06

25 Answers 25

19
\$\begingroup\$

Haskell - 35

c n=(iterate(\x->(x+n/x/x)/2)n)!!99

Example runs:

c 27  =>  3.0
c 64  =>  4.0
c 1  =>  1.0
c 18.609625  =>  2.6500000000000004  # only first 4 digits are important, right?
c 3652264  =>  154.0
c 0.001  =>  0.1
c 7  =>  1.9129311827723892
c (-27)  =>  -3.0
c (-64)  =>  -4.0

Moreover, if you import Data.Complex, it even works on complex numbers, it returns one of the roots of the number (there are 3):

c (18:+26)  =>  3.0 :+ 1.0

The :+ operator should be read as 'plus i times'

\$\endgroup\$
8
  • 1
    \$\begingroup\$ This deserves a +1. I've been refactoring generalized nth root algs for the last hour, and I just now arrived at the same result. Bravo. \$\endgroup\$
    – primo
    Feb 22, 2014 at 14:47
  • \$\begingroup\$ @primo I instantly recalled all n'th root approximation algorithms, and after giving up on Taylor/Maclaurin series in APL I used this. \$\endgroup\$
    – mniip
    Feb 22, 2014 at 15:28
  • \$\begingroup\$ Using Newton method I got x=(2*x+n/x/x)/3, can you explain why you can use x=(x+n/x/x)/2 ? It converges slower but I can't explain why it converges... \$\endgroup\$
    – Michael M.
    Feb 22, 2014 at 15:42
  • \$\begingroup\$ @Michael because if you take x=cbrt(n), then x=(x+n/x/x)/2 is true. So is it true for your expression \$\endgroup\$
    – mniip
    Feb 22, 2014 at 15:50
  • \$\begingroup\$ @Michael I got there this way: codepad.org/gwMWniZB \$\endgroup\$
    – primo
    Feb 22, 2014 at 16:03
8
\$\begingroup\$

SageMath, (69) 62 bytes

However, don't ever believe it will give you the result, it's very difficult to go randomly through all the numbers:

def r(x):
 y=0
 while y*y*y-x:y=RR.random_element()
 return "%.4f"%y

if you didn't insist on truncating:

def r(x):
 y=0
 while y*y*y-x:y=RR.random_element()
 return y

SageMath, 12 bytes, if exp is allowed

Works for all stuff: positive, negative, zero, complex, ...

exp(ln(x)/3)
\$\endgroup\$
7
  • \$\begingroup\$ I believe you are using an operator that can raise a number to a power. \$\endgroup\$
    – user12205
    Feb 22, 2014 at 13:01
  • \$\begingroup\$ ah ok, right, edited \$\endgroup\$
    – yo'
    Feb 22, 2014 at 13:02
  • 7
    \$\begingroup\$ +1 for a monumentally stupid algorithm that still satisfies the requirements. \$\endgroup\$ Feb 22, 2014 at 21:30
  • \$\begingroup\$ @Mechanicalsnail Thanks. I hope it's obvious that what I do is a sort of recession :D However, if exp is allowed, I'm down to 12 and not being stupid at all :) \$\endgroup\$
    – yo'
    Feb 22, 2014 at 21:59
  • \$\begingroup\$ Considering that exp is short for "exponential function", which is "a function whose value is a constant raised to the power of the argument, especially the function where the constant is e.", and there is "No use of methods/operators that can raise a number to a power", exp is not allowed. \$\endgroup\$
    – mbomb007
    Feb 28, 2017 at 15:08
6
\$\begingroup\$

J: 16 characters

Loose translation of the Haskell answer:

-:@((%*~)+])^:_~

Test cases:

   -:@((%*~)+])^:_~27
3
   -:@((%*~)+])^:_~64
4
   -:@((%*~)+])^:_~1
1
   -:@((%*~)+])^:_~18.609625
2.65
   -:@((%*~)+])^:_~3652264
154
   -:@((%*~)+])^:_~0.001
0.1
   -:@((%*~)+])^:_~7
1.91293

It works like this:

     (-:@((% *~) + ])^:_)~ 27
↔ 27 (-:@((% *~) + ])^:_) 27
↔ 27 (-:@((% *~) + ])^:_) 27 (-:@((% *~) + ])) 27
↔ 27 (-:@((% *~) + ])^:_) -: ((27 % 27 * 27) + 27)
↔ 27 (-:@((% *~) + ])^:_) 13.5185
↔ 27 (-:@((% *~) + ])^:_) 27 (-:@((% *~) + ])) 13.5185
↔ 27 (-:@((% *~) + ])^:_) -: ((27 % 13.5185 * 13.5185) + 13.5185)
↔ 27 (-:@((% *~) + ])^:_) 6.83313
...

In words:

half =. -:
of =. @
divideBy =. %
times =. *
add =. +
right =. ]
iterate =. ^:
infinite =. _
fixpoint =. iterate infinite
by_self =. ~

-:@((%*~)+])^:_~ ↔ half of ((divideBy times by_self) add right) fixpoint by_self

Not one of the best wordy translations, since there's a dyadic fork and a ~ right at the end.

\$\endgroup\$
5
\$\begingroup\$

Python - 62 bytes

x=v=input()
exec"x*=(2.*v+x*x*x)/(v+2*x*x*x or 1);"*99;print x

Evaluates to full floating point precision. The method used is Halley's method. As each iteration produces 3 times as many correct digits as the last, 99 iterations is a bit of overkill.

Input/output:

27 -> 3.0
64 -> 4.0
1 -> 1.0
18.609625 -> 2.65
3652264 -> 154.0
0.001 -> 0.1
7 -> 1.91293118277
0 -> 1.57772181044e-30
-2 -> -1.25992104989
\$\endgroup\$
8
  • \$\begingroup\$ How does this work? \$\endgroup\$
    – justhalf
    Feb 22, 2014 at 13:09
  • 1
    \$\begingroup\$ @justhalf I think this is the Newton's method of approximation basically. \$\endgroup\$
    – yo'
    Feb 22, 2014 at 13:10
  • \$\begingroup\$ Btw, fails on 0 \$\endgroup\$
    – yo'
    Feb 22, 2014 at 13:11
  • \$\begingroup\$ Fails on -2, sorry for that. \$\endgroup\$
    – yo'
    Feb 22, 2014 at 13:13
  • 3
    \$\begingroup\$ @plg The problem description forbids the use of any exponential function, otherwise v**(1/.3) would be a sure winner. \$\endgroup\$
    – primo
    Feb 25, 2014 at 19:31
3
\$\begingroup\$

Perl, 92 bytes

sub a{$x=1;while($d=($x-$_[0]/$x/$x)/3,abs$d>1e-9){$x-=$d}$_=sprintf'%.4f',$x;s/\.?0*$//;$_}
  • The function a returns a string with the number without an unnecessary fraction part or insignificant zeroes at the right end.

Result:

              27 --> 3
             -27 --> -3
              64 --> 4
             -64 --> -4
               1 --> 1
              -1 --> -1
       18.609625 --> 2.65
      -18.609625 --> -2.65
         3652264 --> 154
        -3652264 --> -154
           0.001 --> 0.1
          -0.001 --> -0.1
               7 --> 1.9129
              -7 --> -1.9129
 0.0000000000002 --> 0.0001
-0.0000000000002 --> -0.0001
               0 --> 0
              -0 --> 0

Generated by

sub test{
    my $a = shift;
    printf "%16s --> %s\n", $a, a($a);
    printf "%16s --> %s\n", "-$a", a(-$a);
}
test 27;
test 64;
test 1;
test 18.609625;
test 3652264;
test 0.001;
test 7;
test "0.0000000000002";
test 0;

The calculation is based on Newton's method:

Calculation

\$\endgroup\$
3
\$\begingroup\$

Javascript (55)

function f(n){for(i=x=99;i--;)x=(2*x+n/x/x)/3;return x}

BONUS, General formulation for all roots
function f(n,p){for(i=x=99;i--;)x=x-(x-n/Math.pow(x,p-1))/p;return x}

For cube root, just use f(n,3), square root f(n,2), etc... Example : f(1024,10) returns 2.

Explanation
Based on Newton method :

Find : f(x) = x^3 - n = 0, the solution is n = x^3
The derivation : f'(x) = 3*x^2

Iterate :
x(i+1) = x(i) - f(x(i))/f'(x(i)) = x(i) + (2/3)*x + (1/3)*n/x^2

Tests

[27,64,1,18.609625,3652264,0.001,7].forEach(function(n){console.log(n + ' (' + -n + ') => ' + f(n) + ' ('+ f(-n) +')')})

27 (-27) => 3 (-3)
64 (-64) => 4 (-4)
1 (-1) => 1 (-1)
18.609625 (-18.609625) => 2.65 (-2.65)
3652264 (-3652264) => 154 (-154)
0.001 (-0.001) => 0.09999999999999999 (-0.09999999999999999)
7 (-7) => 1.912931182772389 (-1.912931182772389) 
\$\endgroup\$
2
  • \$\begingroup\$ One character shorter: function f(n){for(i=x=99;i--;)x-=(x-n/x/x)/3;return x} \$\endgroup\$
    – copy
    Feb 25, 2014 at 19:01
  • \$\begingroup\$ Can be reduced to 47 bytes f=(n)=>eval('for(i=x=99;i--;)x=(2*x+n/x/x)/3') \$\endgroup\$ Mar 2, 2018 at 14:58
2
\$\begingroup\$

PHP - 81 bytes

Iterative solution:

$i=0;while(($y=abs($x=$argv[1]))-$i*$i*$i>1e-4)$i+=1e-5;@print $y/$x*round($i,4);
\$\endgroup\$
5
  • \$\begingroup\$ What happens if it tries to calculate the cube root of zero? \$\endgroup\$ Feb 22, 2014 at 13:42
  • \$\begingroup\$ It will just output "0" (thanks to the error suppression operator - "@"). \$\endgroup\$
    – Razvan
    Feb 22, 2014 at 13:44
  • 1
    \$\begingroup\$ 0.0001 can be replaced by 1e-4 and 0.00001 by 1e.5. \$\endgroup\$
    – ComFreek
    Feb 22, 2014 at 13:56
  • \$\begingroup\$ This requires PHP<7 (0/0 gives NAN in PHP 7). $i=0; is unnecessary (-5 bytes. If it wasn´t, for would save one byte.) The space after print is not required (-1 byte). -R can save 3 bytes with $argn. \$\endgroup\$
    – Titus
    Feb 28, 2017 at 13:49
  • \$\begingroup\$ Save a pair of parantheses with while(1e-4+$i*$i*$i<$y=abs($x=$argn)) (-2 bytes). \$\endgroup\$
    – Titus
    Feb 28, 2017 at 13:57
2
\$\begingroup\$

APL - 31

(×X)×+/1,(×\99⍴(⍟|X←⎕)÷3)÷×\⍳99

Uses the fact that cbrt(x)=e^(ln(x)/3), but instead of doing naive exponentiation, it computes e^x using Taylor/Maclaurin series.

Sample runs:

⎕: 27
3
⎕: 64
4
⎕: 1
1
⎕: 18.609625
2.65
⎕: 3652264
154
⎕: 0.001
0.1
⎕: 7
1.912931183
⎕: ¯27
¯3
⎕: ¯7
¯1.912931183

Seeing as there's a J answer in 16 characters, I must be really terrible at APL...

\$\endgroup\$
2
\$\begingroup\$

Java, 207 182 181

Sometimes when I play golf I have two many beers and play really really bad

class n{public static void main(String[]a){double d=Double.valueOf(a[0]);double i=d;for(int j=0;j<99;j++)i=(d/(i*i)+(2.0*i))/3.0;System.out.println((double)Math.round(i*1e4)/1e4);}}

Iterative Newton's Method of Approximation, runs 99 iterations.

Here is the unGolfed:

class n{
    public static void main(String a[]){
        //assuming the input value is the first parameter of the input
        //arguments as a String, get the Double value of it
        double d=Double.valueOf(a[0]);
        //Newton's method needs a guess at a starting point for the 
        //iterative approximation, there are much better ways at 
        //going about this, but this is by far the simplest. Given
        //the nature of the problem, it should suffice fine with 99 iterations
        double i=d;

        //make successive better approximations, do it 99 times
        for(int j=0;j<99;j++){
            i=( (d/(i*i)) + (2.0*i) ) / 3.0;
        }
        //print out the answer to standard out
        //also need to round off the double to meet the requirements
        //of the problem.  Short and sweet method of rounding:
        System.out.println( (double)Math.round(i*10000.0) / 10000.0 );
    }
}
\$\endgroup\$
10
  • 1
    \$\begingroup\$ You may rename the args variable to something like z, reducing 6 chars. You may remove the space and the curly braces in the body of the for-loop, reducing 3 chars. You may replace 10000.0 by 1e4, reducing 6 chars. The class does not needs to be public, so you can reduce more 7 chars. This way it will be reduced to 185 characters. \$\endgroup\$ Feb 22, 2014 at 22:07
  • \$\begingroup\$ Is the cast at the end really necessary? It does not for me. \$\endgroup\$ Feb 22, 2014 at 22:13
  • \$\begingroup\$ @Victor Thanks for the good eye, the use of E notation for the 10000.0 double was a spectacularly good idea. By the design of the question, I think it is legit to make this a method instead of a functioning cli class, which would reduce the size considerably. With Java, I didn't think I had a chance, so I erred on the side of functional. \$\endgroup\$
    – md_rasler
    Feb 25, 2014 at 3:28
  • \$\begingroup\$ Welcome to CodeGolf! Don't forget to add an in-answer explanation of how this works! \$\endgroup\$
    – Justin
    Feb 25, 2014 at 6:06
  • \$\begingroup\$ @Quincunx, Thanks, made recommended change. \$\endgroup\$
    – md_rasler
    Feb 25, 2014 at 15:42
2
\$\begingroup\$

TI-Basic, 26 24 bytes

Input :1:For(I,1,9:2Ans/3+X/(3AnsAns:End
\$\endgroup\$
5
  • \$\begingroup\$ That directly uses the ^ operator, doesn't it. It is forbidden by the rules \$\endgroup\$
    – mniip
    Feb 22, 2014 at 20:48
  • \$\begingroup\$ @mniip: Is e^ is a single operator on the TI-83 series? I don't remember. Either way, it's violating the spirit of the rules. \$\endgroup\$ Feb 22, 2014 at 21:29
  • \$\begingroup\$ @Mechanicalsnail It doesn't matter I would say. In most languages you could just do exp(ln(x)/3) or e^(ln(x/3)) if you allowed any of these two. But somehow I understand to exp(ln(x)/a) as too much equivalent to x^(1/a) to be allowed by the rules :-/ \$\endgroup\$
    – yo'
    Feb 22, 2014 at 21:56
  • \$\begingroup\$ Exponential function: "a function whose value is a constant raised to the power of the argument, especially the function where the constant is e." ... "No use of methods/operators that can raise a number to a power" \$\endgroup\$
    – mbomb007
    Feb 28, 2017 at 15:11
  • \$\begingroup\$ Thanks for the catch @mbomb007, I wrote this answer more than 3 years ago and I will fix it to comply now. \$\endgroup\$
    – Timtech
    Feb 28, 2017 at 15:36
2
\$\begingroup\$

Js 57 bytes

f=(x)=>eval('for(w=0;w**3<1e12*x;w++);x<0?-f(-x):w/1e4')

f=(x)=>eval('for(w=0;w**3<1e12*x;w++);x<0?-f(-x):w/1e4')
document.getElementById('div').innerHTML += f(-27) + '<br>'
document.getElementById('div').innerHTML += f(-64) + '<br>'
document.getElementById('div').innerHTML += f(-1) + '<br>'
document.getElementById('div').innerHTML += f(-18.609625) + '<br>'
document.getElementById('div').innerHTML += f(-3652264) + '<br>'
document.getElementById('div').innerHTML += f(-0.001) + '<br>'
document.getElementById('div').innerHTML += f(-7) + '<br><hr>'
document.getElementById('div').innerHTML += f(27) + '<br>'
document.getElementById('div').innerHTML += f(64) + '<br>'
document.getElementById('div').innerHTML += f(1) + '<br>'
document.getElementById('div').innerHTML += f(18.609625) + '<br>'
document.getElementById('div').innerHTML += f(3652264) + '<br>'
document.getElementById('div').innerHTML += f(0.001) + '<br>'
document.getElementById('div').innerHTML += f(7) + '<br>'
<div id="div"></div>

\$\endgroup\$
2
\$\begingroup\$

Javascript: 73/72 characters

This algorithm is lame, and exploits the fact that this question is limited to 4 digits after the decimal point. It is a modified version of the algorithm that I suggested in the sandbox for the purpose of reworking the question. It counts from zero to the infinite while h*h*h<a, just with a multiplication and division trick to handle the 4 decimal digits pecision.

function g(a){if(a<0)return-g(-a);for(h=0;h*h*h<1e12*a;h++);return h/1e4}

Edit, 4 years later: As suggested by Luis felipe De jesus Munoz, by using ** the code is shorter, but that feature was not available back in 2014 when I wrote this answer. Anyway, by using it, we shave an extra character:

function g(a){if(a<0)return-g(-a);for(h=0;h**3<1e12*a;h++);return h/1e4}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Instead h*h*h you can do h**3 and save 1 byte \$\endgroup\$ Mar 2, 2018 at 15:18
  • \$\begingroup\$ @LuisfelipeDejesusMunoz This answer is from 2014. The ** operator was proposed in 2015 and was accepted as part of ECMAScript 7 in 2016. So, at the time that I wrote that, there was no ** in the language. \$\endgroup\$ Mar 2, 2018 at 17:06
1
\$\begingroup\$

Javascript - 157 characters

This function:

  • Handle negative numbers.
  • Handle floating-pointing numbers.
  • Execute quickly for any input number.
  • Has the maximum precision allowed for javascript floating-point numbers.
function f(a){if(p=q=a<=1)return a<0?-f(-a):a==0|a==1?a:1/f(1/a);for(v=u=1;v*v*v<a;v*=2);while(u!=p|v!=q){p=u;q=v;k=(u+v)/2;if(k*k*k>a)v=k;else u=k}return u}

Ungolfed explained version:

function f(a) {
  if (p = q = a <= 1) return a < 0 ? -f(-a)      // if a < 0, it is the negative of the positive cube root.
                           : a == 0 | a == 1 ? a // if a is 0 or 1, its cube root is too.
                           : 1 / f (1 / a);      // if a < 1 (and a > 0) invert the number and return the inverse of the result.

  // Now, we only need to handle positive numbers > 1.

  // Start u and v with 1, and double v until it becomes a power of 2 greater than the given number.
  for (v = u = 1; v * v * v < a; v *= 2);

  // Bisects the u-v interval iteratively while u or v are changing, which means that we still did not reached the precision limit.
  // Use p and q to keep track of the last values of u and v so we are able to detect the change.
  while (u != p | v != q) {
    p = u;
    q = v;
    k = (u + v) / 2;
    if (k * k * k > a)
      v=k;
    else
      u=k
  }

  // At this point u <= cbrt(a) and v >= cbrt(a) and they are the closest that is possible to the true result that is possible using javascript-floating point precision.
  // If u == v then we have an exact cube root.
  // Return u because if u != v, u < cbrt(a), i.e. it is rounded towards zero.
  return u
}
\$\endgroup\$
1
\$\begingroup\$

PHP, 61

Based on Newton's method. Slightly modified version of Michael's answer:

for($i=$x=1;$i++<99;)$x=(2*$x+$n/$x/$x)/3;echo round($x,14);

It works with negative numbers, can handle floating point numbers, and rounds the result to 4 numbers after the decimal point if the result is a floating point number.

Working demo

\$\endgroup\$
1
  • \$\begingroup\$ You can save two bytes with for($x=1;++$i<100;).... But using predefined variables as input is generally frowned upon. Better use $argv[1] or $argn. \$\endgroup\$
    – Titus
    Feb 28, 2017 at 14:06
1
\$\begingroup\$

Befunge 98 - Work in progress

This language does not support floating point numbers; this attempts to emulate them. It currently works for positive numbers that do not start with 0 after the decimal point (mostly). However, it only outputs to 2 decimal places.

&5ka5k*&+00pv
:::**00g`!jv>1+
/.'.,aa*%.@>1-:aa*

It works by inputting the part before the decimal point, multiplying that by 100000, then inputting the part after the point and adding the two numbers together. The second line does a counter until the cube is greater than the inputted number. Then the third line extracts the decimal number from the integer.

If anyone can tell me why the third line only divides by 100 to get the correct values, please tell me.

IOs:

27.0       3 .0
64.0       4 .0
1.0        1 .0
18.609625  2 .65
0.001      0 .1
7.0        1 .91

0.1        0 .1
\$\endgroup\$
1
\$\begingroup\$

Smalltalk, 37

credit goes to mniip for the algorithm; Smalltalk version of his code:

input in n; output in x:

1to:(x:=99)do:[:i|x:=2*x+(n/x/x)/3.0]

or, as a block

[:n|1to:(x:=99)do:[:i|x:=2*x+(n/x/x)/3.0].x]
\$\endgroup\$
1
\$\begingroup\$

GameMaker Language, 51 bytes

for(i=x=1;i++<99;1)x=(2*x+argument0/x/x)/3;return x
\$\endgroup\$
0
\$\begingroup\$

Haskell: 99C

Can't beat @mniip in cleverness. I just went with a binary search.

c x=d 0 x x
d l h x
 |abs(x-c)<=t=m
 |c < x=d m h x
 |True=d l m x
 where m=(l+h)/2;c=m*m*m;t=1e-4

Ungolfed:

-- just calls the helper function below
cubeRoot x = cubeRoot' 0 x x

cubeRoot' lo hi x
    | abs(x-c) <= tol = mid           -- if our guess is within the tolerance, accept it
    | c < x = cubeRoot' mid hi x      -- shot too low, narrow our search space to upper end
    | otherwise = cubeRoot' lo mid x  -- shot too high, narrow search space to lower end
    where
        mid = (lo+hi)/2
        cubed = mid*mid*mid
        tol = 0.0001
\$\endgroup\$
3
  • \$\begingroup\$ You can use an infix operator for d (like (l#h)x) to save a byte for each call. c then becomes id>>=(0#). \$\endgroup\$ Mar 2, 2018 at 15:13
  • \$\begingroup\$ You can remove spaces around c < x. \$\endgroup\$ Mar 2, 2018 at 15:13
  • \$\begingroup\$ You can use 1>0 instead of True. \$\endgroup\$ Mar 2, 2018 at 15:14
0
\$\begingroup\$

J 28

*@[*(3%~+:@]+(%*~@]))^:_&|&1

Using Newtons method, finding the root of x^3 - X the update step is x - (x^3 - C)/(3*x^2), where x is the current guess, and C the input. Doing the maths on this one yields the ridiculously simple expression of (2*x+C/x^2) /3 . Care has to be taken for negative numbers.

Implemented in J, from right to left:

  1. | Take abs of both arguments, pass them on
  2. ^:_ Do until convergence
  3. (%*~@]) is C / x^2 (*~ y is equivalent to y * y)
  4. +:@] is 2 x
  5. 3%~ divide by three. This yields the positive root
  6. *@[ * positive_root multiplies positive root with the signum of C.

Test run:

   NB. give it a name:
   c=: *@[*(3%~+:@]+(%*~@]))^:_&|&1
   c 27 64 1 18.609625 3652264 0.001 7
3 4 1 2.65 154 0.1 1.91293
\$\endgroup\$
0
\$\begingroup\$

AWK, 53 bytes

{for(n=x=$1;y-x;){y=x;x=(2*x+n/x/x)/3}printf"%.4g",y}

Example usage:

$ awk '{for(n=x=$1;y-x;){y=x;x=(2*x+n/x/x)/3}printf"%.4g",y}' <<< 18.609625 
2.65$

Thanks go to @Mig for the JavaScript solution which this is derived from. It runs surprisingly quickly given that the for loop requires the iteration to stop changing.

\$\endgroup\$
0
\$\begingroup\$

C, 69 bytes

i;float g(float x){for(float y=x;++i%999;x=x*2/3+y/3/x/x);return x;}

Just another implementation of Newton's method. Try it online!

\$\endgroup\$
0
\$\begingroup\$

Stax, 10 bytesCP437

╘♀┘A╕äO¶∩'

Run and debug online!

Explanation

Uses the unpacked version to explain.

gpJux*_+h4je
gp              Iterate until a fixed point is found, output the fix point
  Ju            Inverse of square
    x*          Multiplied by input
      _+h       Average of the value computed by last command and the value at current iteration
         4je    Round to 4 decimal digits
  
\$\endgroup\$
0
\$\begingroup\$

JAVA Solution

public BigDecimal cubeRoot(BigDecimal number) {

    if(number == null || number.intValue() == 0) return BigDecimal.ZERO;
    BigDecimal absNum = number.abs();
    BigDecimal t;
    BigDecimal root =  absNum.divide(BigDecimal.valueOf(3), MathContext.DECIMAL128);


    do {

        t = root;
        root = root.multiply(BigDecimal.valueOf(2))
                .add(absNum.divide(root.multiply(root), MathContext.DECIMAL128))
                .divide(BigDecimal.valueOf(3), MathContext.DECIMAL128);

    } while (t.toBigInteger().subtract(root.toBigInteger()).intValue() != 0);

    return root.multiply(number.divide(absNum), MathContext.DECIMAL128);
}
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Welcome to PPCG! This is a code-golf challenge, which means the goal is to solve the challenge is as little code as possible (counted in bytes of the source file). You should show some effort towards optimising your solution towards that goal and include the byte count in your answer. \$\endgroup\$ Mar 26, 2018 at 15:30
0
\$\begingroup\$

Python Solution

def cube_root(num):
    if num == 0:
        return 0

    t = 0
    absNum = abs(num)
    root = absNum/3

    while (t - root) != 0:
        t = root
        root = (1/3) * ((2 * root) + absNum/(root * root))

    return root * (num / absNum)
\$\endgroup\$
0
0
\$\begingroup\$

MMIX, 44 bytes (11 instrs)

E0013FF0 48000002 E8018000 C1FF0100
1001FFFF 14010001 040101FF E401FFF0
11FF01FF 53FFFFFA F8020000

Disassembly

cbrt    SETH  $1,#3FF0      // y = 1.
        BNN   $0,0F         // if(x >= 0) goto loop (ensuring sign is correct)
        ORH   $1,#8000      // y = fnabs(y) (bit tricks!)
0H      SET   $255,$1       // loop: prev = y
        FMUL  $1,$255,$255  // y = prev *. prev
        FDIV  $1,$0,$1      // y = x /. y
        FADD  $1,$1,$255    // y = y +. prev
        INCH  $1,#FFF0      // y = y /. 2. (bit tricks again)
        FCMPE $255,$1,$255  // prev = comp_eps(y, prev)
        PBNZ  $255,0B       // if(prev) goto loop
        POP   2,0           // return {y,x}

It is up to the caller to set a suitable value of rE. Much faster convergence may be arranged by essentially setting y up by dividing the exponent by 3, but that costs another four instructions (though in time it pays really quickly, since three FDIVs cost about the same amount as two DIVs):

cbrt    SLU  $1,$0,1    // 3B010001 shift left to erase sign
        INCH $1,#8020   // E4018020 unbias exponent
        DIV  $1,$1,3    // 1D010103 divide by 3 as integer; approximate cube root
        INCH $1,#7FE0   // E4017FE8 rebias exponent
        SRU  $1,$1,1    // 3F010101 shift right again

and then continue from the second line in the original.

If mispredicted branches are particularly expensive, I would also replace the second and third lines of the original with:

        ZSN $255,$0,1       // 71020001 $255 = ($0 neg? 1 : 0)
        SLU $255,$255,63    // 3B02023F $255 <<= 63
        OR  $1,$1,$255      // C0010102 $1 |= $255

This costs one more instruction, but is branchless.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.