20

trunc and int functions return the same output for every float type inputs that I have tried.

They differ in the way that int can also be used to convert numerical strings to integers.

So I have a two-fold question:

  1. I would like to know if, apart from strings, is there any input for which trunc and int give different outputs?

  2. If not, when is it better to just use trunc to convert floating type numbers to integers?

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
whateven
  • 344
  • 4
  • 9
  • 4
    If the output type and value for floats is the same for both, what classifies **better** for you? – Sheldore Sep 07 '18 at 13:33
  • 4
    @Bazingaa I think the question is more along the lines of whether anyone can think of a use case where it would actually be correct to use `trunc` over `int`, not which one is *better*. Confirming that they are actually identical could be an answer as well. – sobek Sep 07 '18 at 13:37
  • 2
    The exception of already mentioned example of `strings` already rules out the possibility of them being identical. – Sheldore Sep 07 '18 at 13:39
  • 1
    So one possible use case is if i want the cast to throw an error if some other dtype than `float` is used, i could use `trunc`. – sobek Sep 07 '18 at 13:43
  • @Bazingaa perhaps due to some fundamental difference in their implementation one of them is implemented faster in case of very big numbers. – whateven Sep 07 '18 at 14:27
  • @whateven: So speed is what you were looking for. That explains – Sheldore Sep 07 '18 at 14:33

2 Answers2

18

int and math.trunc have a somewhat similar relationship as str and repr. int delegates to a type's __int__ method, and falls back to the __trunc__ method if __int__ is not found. math.trunc delegates to the type's __trunc__ method directly and has no fallback. Unlike __str__ and __repr__, which are always defined for object, both int and math.trunc can raise errors out of the box.

For all the built-in types that I am aware of, both __int__ and __trunc__ are defined sensibly where appropriate. However, you can define your own set of test classes to see what errors you get:

class A:
    def __int__(self):
        return 1

class B:
    def __trunc__(self):
        return 1

class C(): pass

math.trunc(A()) and math.trunc(C()) will both raise TypeError: type X doesn't define __trunc__ method. int(C()) will raise TypeError: int() argument must be a string, a bytes-like object or a number, not 'C'. However, int(A()), int(B()) and math.trunc(B()) will all succeed.

In the end the decision as to which method to use is one of connotation. trunc is inherently a math operation similar to floor, while int is a general purpose conversion, and succeeds in more cases.

And don't forget about operator.index and the __index__ method.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • 3
    Note also that `__int__` should (must?) return a value of type `int`, while `__trunc__` merely needs to return a value of type `Integral` (an abstract base class). Commonly, but not necessarily, the concrete type of the returned value is `int`. – chepner Sep 07 '18 at 14:05
  • @chepner. Should :) If you use an improperly implemented `__int__` very carefully, it won't cause you any problems. I've definitely tried similar things. – Mad Physicist Sep 07 '18 at 14:10
0

math.trunc() works about 10% faster than int(); at least on my computer configuration.

cottontail
  • 10,268
  • 18
  • 50
  • 51