# Reverse an integer regardless of its sign

Hello.

Trying to reverse an integer regardless of its sign I wrote the following algorithm:

``````int = -123456789 #=> Expected result -987654321

def minus_one(int) do
int * -1
end

def sign(int) when int > 0 do
int
|> Integer.to_string()
|> String.reverse()
|> String.to_integer()
end

def sign(int) do
int
|> Integer.to_string()
|> String.replace("-", "")
|> String.reverse()
|> String.to_integer()
|> minus_one()
end

def reverse_integer(int) do
sign(int)
end
``````

Is there a native way to get the sign of a number? like :math.sign()

Any suggestions to improve the algorithm is welcome.

Thanks.

``````def sign(int) when int >= 0, do: 1
def sign(int) when int < 0, do: -1

def reverse(int) when int >= 0 do
int
|> Integer.to_string()
|> String.reverse()
|> String.to_integer()
end

def reset_sign(int, 1), do: int
def reset_sign(int, -1), do: int * -1

def reverse_integer(int) do
int
|> abs()
|> reverse()
|> reset_sign(sign(int))
end
``````
3 Likes

Iâ€™ve previously looked for functions akin to `neg?`, `pos?`, and `zero?` in the standard library but I couldnâ€™t find anything.

I hesitate to call it an improvement , but hereâ€™s what I came up with:

``````defmodule MyInt do
defp sign_prefix(int) when int < 0, do: "-"
defp sign_prefix(int), do: ""

def reverse(int) when is_integer(int) do
reversed_int = int
|> Integer.to_string
|> String.reverse

"#{sign_prefix(int)}#{reversed_int}"
|> String.to_integer
end
end
``````
1 Like

Have you seen `:erlang.integer_to_list/1` and `:erlang.list_to_integer/1`?

EDIT: Elixir actually provides these through respectively `Integer.to_charlist/1` and `List.to_integer/1`

1 Like

@Andres: I can see much simpler way:

``````defmodule Example do
def sample(integer) when is_integer(integer) do
integer |> Integer.digits() |> Enum.reverse() |> Integer.undigits()
end
end
``````

Is that what you wanted?

Edit: Code changed after @Ted comment

6 Likes

Wow, that is clean!

Iâ€™m curious about the reason for two function heads because it seems like the first head works for both positive and negative:

``````iex(7)> 123 |> Integer.digits() |> Enum.reverse() |> Integer.undigits()
321
iex(8)> -123 |> Integer.digits() |> Enum.reverse() |> Integer.undigits()
-321
``````
1 Like

Hello @LostKobrakai

Super nice patter matching idea

Yes!

Iâ€™m learning so much, thanks for sharing.

Why converting to a string at all?

Just do the maths:

``````defmodule DR do
def r(n), do: r(n, 0)

def r(0, x), do: x
def r(n, x), do: r(div(n, 10), x * 10 + rem(n, 10))
end
``````
6 Likes

Hello @Ted

, Super nice!
I didnâ€™t know that was possible. Iâ€™m learning so much, thanks for sharing.

Ah right, my bad - I have edited my first post

2 Likes
`````` -123_456_789
|> Integer.digits() # => [-1, -2, -3, -4, -5, -6, -7, -8, -9]
|> Enum.reverse() # => [-9, -8, -7, -6, -5, -4, -3, -2, -1]
|> Integer.undigits() # => -987654321
``````

But:

``````Integer.undigits([1, -2, 3]) # => 83
``````

This seems a very good topic of conversation.

Hi @NobbZ
Thanks so much for sharing.

Originally I noticed this on other data too, but I found that it is not a problem in this specific case, because as far as I know `Integer.digits/1` will never return list like `[1, -2, 3]`.

There is nothing surprising with `83` as result, because we have: `(3 * 10^0) + (-2 * 10^1) + (1 * 10^2)` i.e. `(3 * 1) + (-2 * 10) + (1 * 100)` i.e. `3 - 20 + 100` which gives `83`.

4 Likes

Thank you very much for clarifying it.

2 Likes