Passing larger number to div function - why doesn't this work?

whats wrong with this syntax

# this works: this is :math.pow(26,26)
61561195802071577546418399337250816|> div(26)
# but this won't
:math.pow(26,26)|> div(26)
# neither this:
6.156119580207158e36|>div(26)

div works for integer…

why not use / ?

iex> :math.pow(26,26)/26
2.367738300079676e35
iex> 6.156119580207158e36/26      
2.367738300079676e35
3 Likes
# how to get remainder, I don't see a % operator . For uniformity I thought i will use div and rem functions.
6.156119580207158e36|>rem(26)
iex(8)> :math.pow(26,26) == 61561195802071577546418399337250816
false

:math.pow(26,26) produces a float not an integer. Div doesn’t work with floats.

4 Likes

You can use trunc/1 to convert a floating point to an integer. trunc converts a float to the closest less than or equal integer value

iex(84)> :math.pow(26, 26) |> trunc |> rem(26)
0

div/2 and rem/2 are only defined for integer inputs because they are fundamentally about integer math

2 Likes

ic! so there no elixir equivalent for a ruby code which looks like this ? (in other words how to find remainders for a float? )

irb(main):007:0> (100 ** 100) % 12345
=> 10030
irb(main):008:0>

The problem is that the result from :math.pow/2 is a float in IEEE 754 format (from a C library) which isn’t precise.

iex(1)> defmodule Test do
...(1)>   use Bitwise
...(1)> 
...(1)>   def pow(_, 0) do
...(1)>     1
...(1)>   end
...(1)> 
...(1)>   def pow(x, 1) do
...(1)>     x
...(1)>   end
...(1)> 
...(1)>   def pow(x, y) do
...(1)>     z = pow(x, y >>> 1)
...(1)>     w = if((y &&& 1) === 0, do: 1, else: x)
...(1)>     z * z * w
...(1)>   end
...(1)> end
{:module, Test,
 <<70, 79, 82, 49, 0, 0, 5, 136, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 133,
   0, 0, 0, 16, 11, 69, 108, 105, 120, 105, 114, 46, 84, 101, 115, 116, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 7, 99, ...>>, {:pow, 2}}
iex(2)> 
nil
iex(3)> Test.pow(100, 100) |> rem(12345)
10030
iex(4)> 

https://stackoverflow.com/questions/38533797/how-to-calculate-5262144-in-erlang/38534076#answer-38534076

1 Like

Even aside from the specifics of the IEEE floating point number representation, a remainder from dividing a decimal number by another number really doesn’t make mathematical sense. You have a decimal, you divide, you get a decimal back. Remainders only matter when you are dealing in the domain of whole number integers.

Ruby was just hiding that from you by implicitly casting your float to an integer.

1 Like

thanks, It was a question out of Curiosity on how Elixir deals with extremely larger numbers.

It does not:

3.5 % 3 #=> 0.5
3 % 2.5 #=> 0.5

Neither of its arguments seems to be converted to integer. I get a result that is expected and would hold the usual n = m * d + r (+/- IEEE inaccuracy).

Sadly it seems as if I am not able to get d for floats easily in ruby which makes the % behaviour pretty useless…

1 Like

You should have said so! It transparently uses bignums Arbitrary-precision arithmetic - Wikipedia limited only by available memory

2 Likes

My apology for mis-speaking. I was speaking about the conceptual nature of div and rem only making sense for integers. I honestly have no idea how Ruby implements it.

1 Like

@gregvaughn, Thank you for the update. Syntax below seems to be one way of solving it.

 round(:math.pow(100,100))

https://floating-point-gui.de/errors/rounding/

And :math functions don’t calculate with bignums - 64-bit IEEE standard floating point results are converted to bignum values locking in the inherent loss in precision.

So

iex(2)>  :math.pow(100, 100) |> trunc |> rem(12345)
398
iex(3)>  :math.pow(100, 100) |> round |> rem(12345)
398
iex(4)> 

is wrong either way.

https://stackoverflow.com/questions/19893708/will-erlang-have-bignums-for-math-functions#answer-19895350

1 Like

thanks. So there isn’t any out of the box solution for this in Elixir.(an equivalent syntax from ruby is given below)

2.6.0 :002 > number = 100 ** 100
=> 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2.6.0 :003 > number.divmod(26)
=> [3846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153, 22]
iex(1)> num = [100] |> Stream.cycle |> Enum.take(100) |> Enum.reduce(&(&1*&2))
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
iex(2)> {div, mod} = {div(num, 26), rem(num, 26)}
{3846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153846153,
 22}

Not exactly as nice, but easily implementable in a helper function…

1 Like