How do I calculate the cube root?

I am trying to find all numbers with an integer cube root, but it hasn’t worked because appareantly cbrt() isn’t a processing supported function. how do I do this?
this is my code:

int x= 1;
if(cbrt(x)==int(cbrt(x)){
  println(x);
}
else{
  x++;
}

You can have a look at this wikipedia article: nth root - Wikipedia

Indeed Processing devs think cbrt() usage is so rare it wasn’t worth to be included in Processing’s API.

However Java got that cbrt() function in its Math class; but it returns a double instead of a float value:
docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Math.html#cbrt(double)

We can also use pow() passing 1/3. as its 2nd argument in order to emulate cbrt(): pow(x, 1/3.)
println(Math.cbrt(27) == pow(27, 1/3.)); // true

1 Like

does pow also work for negative numbers?

Click at the pow()'s reference link I’ve posted and you’ll see examples w/ negative values as well.

1 Like

I did but this code print NaN

int x= -1;
void draw() {
  if (pow(x, 1/3.)==int(pow(x, 1/3.))) {
    //println(x);
  }
  x=x-1;
  println(pow(x, 1/3.));
}
for (int x = 1; x < 100; x++) {
  if (Math.cbrt(x) == (int)Math.cbrt(x))
    println(x);
}

Gives the result

1
8
27
64

which is what you are looking for

That’s a shortcoming of using pow() w/ negative bases & fractional exponents.

If you don’t wanna use Java’s own Math.cbrt() (maybe b/c you prefer your code to also run online via Pjs) and choose to stick w/ Processing’s pow() you can make your own cbrt() using pow():

// https://Discourse.Processing.org/t/how-do-i-calculate-the-cube-root/33988/8
// GoToLoop (2021/Dec/07)

import java.util.Map;
final Map<Integer, Integer> roots = new HashMap<Integer, Integer>();

static final int MIN_BASE = -125, MAX_BASE = 125;

void setup() {
  for (int i = MIN_BASE; i <= MAX_BASE; ++i) {
    final float root = cbrt(i), rootThreeDecimals = round(root * 1e3) / 1e3;
    final int roundedRoot = round(root);

    if (rootThreeDecimals == roundedRoot)  roots.put(i, roundedRoot);
  }

  println(roots);
  println(roots.size()); // 11

  exit();
}

static final float cbrt(final float n) {
  return n < 0? -pow(-n, 1/3.) : pow(n, 1/3.);
}
1 Like

If you want to want to calculate the cube root of a real number using only the 4 basic math operators, (+ - * /) then you might try this out - it works :grinning_face_with_smiling_eyes:

float a3 = -1.25*-1.25*-1.25;
float b3 = 1234*1234*1234;
float[] f = { 125, -64, a3, b3};

void setup() {
  for (float n : f)
    calculateAndDislay(n);
}

void calculateAndDislay(float x) {
  print("Cube root of " + x + " is ");
  println((float) cbrt(x));
}

// Use Halley's method to find the cube root of a real number
double cbrt(double x) {
  if(x == 0) return 0;
  double epsilon = 1e-6;
  double r0 = x / 3;
  double r, diff;
  do {
    double rc = r0 * r0 * r0;
    r = r0 * (rc + 2 * x) / (2 * rc + x);
    diff = r - r0;
    r0 = r;
  } while (diff < -epsilon || diff > epsilon);
  return r;
}
2 Likes

thank you, I have another question, how do I make it only print the numbers if they are not infinitly repeating?

int x= -1;

void draw(){
  float y=pow(x, 1.5);
  if (Math.cbrt(x) == (int)Math.cbrt(x)){
    println(x);
  }
  x=x-1;
}

There are an infinite number of numbers that have an integer cube root, so we cannot find all of them. But to calculate a number that has an integer cube root, all you need to do is cube an integer. Accordingly, to find the first n numbers that have an integer cube root, just cube the first n integers. There’s no need to actually calculate any cube roots to do this.

Following is a Python program that displays the first 11 numbers that have an integer cube root, along with their cube roots:

for cube_root in range(11):
     print("{:4d} {:4d}".format(cube_root ** 3, cube_root))

Output:

   0    0
   1    1
   8    2
  27    3
  64    4
 125    5
 216    6
 343    7
 512    8
 729    9
1000   10

In the above, we did not need to calculate any cube roots.

On the other hand, if you wish to write a function that, given a number, calculates its cube root, one algorithm to consider is Newton’s method.

See the following:

The following Python function, written for Python 3, and decidedly not for Python 2, uses Newton’s method to calculate a cube root:

def cube_root(n):
    # uses Newton's method
    n = float(n)
    # estimate the cube root
    est = n / 2
    prev_diff = max(n, 1)
    while True:
        # assign new_est the average of est and n / est * est
        new_est = (est + n / (est * est)) / 2
        # check how much the estimate has changed
        curr_diff = abs(est - new_est)
        # if the change has stopped decreasing, break and return the result
        if curr_diff >= prev_diff:
            break
        # otherwise keep refining the estimate
        prev_diff = curr_diff
        est = new_est
    return new_est

print(cube_root(1311494070536))

Output:

10946.0
2 Likes

That statement is definitely wrong b/c your posted code can be pasted and successfully run in Processing’s Python Mode (Jython), which is based on Python 2.

Also I’ve taken the opportunity to convert your cube root algorithm to Processing’s Java Mode:

void setup() {
  println(cbrt(-1311494070536L)); // -10946.0
  exit();
}

static final float cbrt(final float n) {
  //return n < 0? -pow(-n, 1/3.) : pow(n, 1/3.);

  if (n == 0)  return 0;

  final float v = abs(n), sign = n > 0? 1 : -1;
  float est = v * .5, prevDiff = max(v, 1);

  while (true) {
    final float newEst = (v / sq(est) + est) * .5, currDiff = abs(est - newEst);

    if (currDiff >= prevDiff)  return newEst * sign;

    est = newEst;
    prevDiff = currDiff;
  }
}
2 Likes

I should have stated, instead, that I have tested it quite a bit with Python 3, but have not tested it much on very large numbers with Python 2.

1 Like

If you are going to use numerical methods to calculate the cube root then I suggest you use Halley’s method rather than Newton’s method as it converges on the answer more quickly and is just as easy to implement.

@javagar The Python method does not calculate the cube root of negative numbers correctly for instance cube_root(-125) returns -31.266 rather than the correct answer of -5. The problem is in the terminating condition of the while loop. You should not compare the differences between 2 iterations rather compare the answer from 2 successive iterations and see it it is less than some small value.

@GoToLoop 's Java conversion of your code corrects the issue of negative roots by getting the sign of the number to be cube rooted but this can also be avoided by comparing successive estimates rather than successive differences.

3 Likes

Thanks, @GoToLoop and @quark, for your contributions, observations, and suggestions.

2 Likes