316

I am trying to find the largest cube root that is a whole number, that is less than 12,000.

processing = True n = 12000 while processing: n -= 1 if n ** (1/3) == #checks to see if this has decimals or not 

I am not sure how to check if it is a whole number or not though! I could convert it to a string then use indexing to check the end values and see whether they are zero or not, that seems rather cumbersome though. Is there a simpler way?

2
  • 5
    it would make it easier to work from the cube root n --> (n * n * n < 12000) Commented Feb 5, 2014 at 17:09
  • 1
    Btw do you mean largest integer cube? That can be computed for small values by rounding down with int(12000**(1/3))**3 Commented Dec 30, 2022 at 2:50

15 Answers 15

591

To check if a float value is a whole number, use the float.is_integer() method:

>>> (1.0).is_integer() True >>> (1.555).is_integer() False 

The method was added to the float type in Python 2.6.

Take into account that in Python 2, 1/3 is 0 (floor division for integer operands!), and that floating point arithmetic can be imprecise (a float is an approximation using binary fractions, not a precise real number). But adjusting your loop a little this gives:

>>> for n in range(12000, -1, -1): ... if (n ** (1.0/3)).is_integer(): ... print n ... 27 8 1 0 

which means that anything over 3 cubed, (including 10648) was missed out due to the aforementioned imprecision:

>>> (4**3) ** (1.0/3) 3.9999999999999996 >>> 10648 ** (1.0/3) 21.999999999999996 

You'd have to check for numbers close to the whole number instead, or not use float() to find your number. Like rounding down the cube root of 12000:

>>> int(12000 ** (1.0/3)) 22 >>> 22 ** 3 10648 

If you are using Python 3.5 or newer, you can use the math.isclose() function to see if a floating point value is within a configurable margin:

>>> from math import isclose >>> isclose((4**3) ** (1.0/3), 4) True >>> isclose(10648 ** (1.0/3), 22) True 

For older versions, the naive implementation of that function (skipping error checking and ignoring infinity and NaN) as mentioned in PEP485:

def isclose(a, b, rel_tol=1e-9, abs_tol=0.0): return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) 
Sign up to request clarification or add additional context in comments.

10 Comments

Not knowing python, this sort of statement would make me nervous as it seems to require perfect math to work in the real world.
@PeterM: The method indeed only returns True if there are no decimals at all. There may be a misunderstanding on the part of the OP about floating point arithmetic and precision, of course.
@MartijnPieters Yeah and one small slip in a floating point calculation and all of a sudden you have these little, unwanted decimals like 0.00000000000000000001
@PeterM: and in Python 2 the default representation will round to 16 digits; 1.0000000000000001 is displayed as 1.0, in 3 the shortest string representation that produces the same value is shown.
Your range(12000, -1, -1) could be (imo, more cleanly) rewritten as reversed(range(12000+1))
|
74

We can use the modulo (%) operator. This tells us how many remainders we have when we divide x by y - expresses as x % y. Every whole number must divide by 1, so if there is a remainder, it must not be a whole number.

This function will return a boolean, True or False, depending on whether n is a whole number.

def is_whole(n): return n % 1 == 0 

1 Comment

This is the better answer because it also works if n happens to be an integer. The accepted answer will fail in that case.
21

You could use this:

if k == int(k): print(str(k) + " is a whole number!") 

7 Comments

it fails for larger numbers while .is_integer() continues to work.
Your link IMHO doesn't show that it doesn't work. It just shows that large floats lose precision. is_integer uses a similar method (o = (floor(x) == x) ? Py_True : Py_False;). But I agree, one should use is_integer() as it is much clearer.
yes. It just shows that large float may lose precision i.e., large_float == large_int may fail even if large_float == float(large_int).
123456789012345678901234567890.0 != 123456789012345678901234567890 but 123456789012345678901234567890.0 == float(123456789012345678901234567890)
Yeah, but k = 123456789012345678901234567890.0 then k == int(k) is True, which is the correct answer.
|
13

You don't need to loop or to check anything. Just take a cube root of 12,000 and round it down:

r = int(12000**(1/3.0)) print r*r*r # 10648 

Comments

9

You can use a modulo operation for that.

if (n ** (1.0/3)) % 1 != 0: print("We have a decimal number here!") 

2 Comments

if n is 6.2, 6.0, 6.12312412, we all have "We have a decimal number here!"?
@JayWong not sure how you loaded your test, but this works fine on my machine using Python3.7.
7

How about

if x%1==0: print "is integer" 

Comments

6

Wouldn't it be easier to test the cube roots? Start with 20 (20**3 = 8000) and go up to 30 (30**3 = 27000). Then you have to test fewer than 10 integers.

for i in range(20, 30): print("Trying {0}".format(i)) if i ** 3 > 12000: print("Maximum integral cube root less than 12000: {0}".format(i - 1)) break 

1 Comment

Moreover, floats have round-off errors so that you can miss number when calculating if n**(1/3) is integer. For example on my computer ` 10648**(1/3)=21.999999999999996 ` instead of 22: problem! With this answer's method there is no such problem. I think this is the only correct solution from a mathematic point of view (others solutions are Python-correct).
5

The above answers work for many cases but they miss some. Consider the following:

fl = sum([0.1]*10) # this is 0.9999999999999999, but we want to say it IS an int 

Using this as a benchmark, some of the other suggestions don't get the behavior we might want:

fl.is_integer() # False fl % 1 == 0 # False 

Instead try:

def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) def is_integer(fl): return isclose(fl, round(fl)) 

now we get:

is_integer(fl) # True 

isclose comes with Python 3.5+, and for other Python's you can use this mostly equivalent definition (as mentioned in the corresponding PEP)

1 Comment

math.fsum([0.1] * 10) == 1
3

Just a side info, is_integer is doing internally:

import math isInteger = (math.floor(x) == x) 

Not exactly in python, but the cpython implementation is implemented as mentioned above.

Comments

2

You can use something like:

num = 1.9899 bool(int(num)-num) #returns True 

if it is True, It means it holds some value, hence not a whole number. Else

num = 1.0 bool(int(num)-num) # returns False 

Comments

1

All the answers are good but a sure fire method would be

def whole (n): return (n*10)%10==0 

The function returns True if it's a whole number else False....I know I'm a bit late but here's one of the interesting methods which I made...

Edit: as stated by the comment below, a cheaper equivalent test would be:

def whole(n): return n%1==0 

1 Comment

This should be no functionally different than n % 1 == 0. In this case, you're doing two operations which is more expensive for a cheaper equivalent test.
0
>>> def is_near_integer(n, precision=8, get_integer=False): ... if get_integer: ... return int(round(n, precision)) ... else: ... return round(n) == round(n, precision) ... >>> print(is_near_integer(10648 ** (1.0/3))) True >>> print(is_near_integer(10648 ** (1.0/3), get_integer=True)) 22 >>> for i in [4.9, 5.1, 4.99, 5.01, 4.999, 5.001, 4.9999, 5.0001, 4.99999, 5.000 01, 4.999999, 5.000001]: ... print(i, is_near_integer(i, 4)) ... 4.9 False 5.1 False 4.99 False 5.01 False 4.999 False 5.001 False 4.9999 False 5.0001 False 4.99999 True 5.00001 True 4.999999 True 5.000001 True >>> 

1 Comment

Here are some guidelines for How do I write a good answer?. This provided answer may be correct, but it could benefit from an explanation. Code only answers are not considered "good" answers. From review.
0

This problem has been solved, but I would like to propose an additional mathematical-based solution for funcies.

The benefit of this approach is that it calculates the whole number part of your number, which may be beneficial depending on your general task.

Algorithm:

  • Decompose whole number part of your number its a sum of its decimals (e.g., 327=3*100+2*10+7*1)
  • take difference between calculated whole number and number itself
  • decide whether difference is close enough to be considered an integer.
from math import ceil, log, isclose def is_whole(x: float) -> bool: n_digits = ceil(log(x,10)) # number of digits of decimals at or above ones digits = [(n//(10**i))%10 for i in range(n_digits)] # parse digits of `x` at or above ones decimal whole = 0 # will equal the whole number part of `x` for i in range(n_digits): decimal = 10**i digit = digits[i] whole += digit*decimal diff = whole - x return isclose(diff, 0.0) 

NOTE: the idea of parsing digits of a number was realized from here

Comments

-1

Try using:

int(val) == val 

It will give lot more precision than any other methods.

1 Comment

Can you give an example to back up the claim that "It will give lot more precision"? This seems unfounded.
-1

You can use the round function to compute the value.

Yes in python as many have pointed when we compute the value of a cube root, it will give you an output with a little bit of error. To check if the value is a whole number you can use the following function:

def cube_integer(n): if round(n**(1.0/3.0))**3 == n: return True return False 

But remember that int(n) is equivalent to math.floor and because of this if you find the int(41063625**(1.0/3.0)) you will get 344 instead of 345.

So please be careful when using int withe cube roots.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.