Basic I/O and more

#1

Hi Everyone. I have some simple questions.
1 - What is the best(time and space wise) way to read 3 integers in a single line from stdin or a file? How about if there are arbitrary numbers of integers in a line and you need to process each(e.g. check each integer for primality)? These are inside a loop of course.
2 - Is there a faster way than printf for output?
3 - What’s the most efficient way to implement mulmod(modular multiplication) considering that the product might overflow? Is there a chance that it can be added as a built-in function like powermod(why not powmod?) and invmod?
4 - How can I have a guarantee that my local constant variable won’t be accidentally modified? From what I know, const works only for global variables.

#2

Are you talking about parsing integers or reading them represented as binary data?

2 - Is there a faster way than printf for output?

Doing print(io, n) is efficient.

3 - What’s the most efficient way to implement mulmod(modular multiplication) considering that the product might overflow? Is there a chance that it can be added as a built-in function like powermod(why not powmod?) and invmod?

Not really a Julia question. If you find a good algorithm for this, implementing it should be straightforward and would make either a good package or contribution to Base. I agree that the naming of invmod and powermod are annoyingly inconsistent. That one slipped through the 1.0 naming review process. We could always rename it to powmod and keep powermod as a legacy alias.

4 - How can I have a guarantee that my local constant variable won’t be accidentally modified? From what I know, const works only for global variables.

You can’t. It’s a planned feature but currently const only works on globals.

1 Like
#3

Are you talking about parsing integers or reading them represented as binary data?

As Integers

Not really a Julia question. If you find a good algorithm for this, implementing it should be straightforward and would make either a good package or contribution to Base. I agree that the naming of invmod and powermod are annoyingly inconsistent. That one slipped through the 1.0 naming review process. We could always rename it to powmod and keep powermod as a legacy alias

When will ‘powmod’ be available? ‘powermod’ is a little bit awkward to use.

Additional questions:

  1. Is there a plan to add ‘and’ and ‘or’ as aliases for ‘&&’ and ‘||’. These are pretty common for high level languages.
  2. How can I translate the below c++ code to Julia. I thought of zip but maybe there’s a better way.

for (int i = 0, j = 0, k = 0; i < 10 && j < 100 && k <1000; ++i, ++j, ++k)

#4

You can have it whenever you like.

const powmod = powermod

No. https://github.com/JuliaLang/julia/issues/5238#issuecomment-354499909

In the general case you should consider C++ for as equivalent to a while construction in Julia. In some common cases it can be transformed to a Julia for loop but that depends on how the loop variables are used. Since the loop in this case is unnecessarily complicated unless the loop variables are modified in the body, the most direct translation would be

i = j = k = 0
while i < 10 && j < 100 && k <1000
    [body]
    i += 1; j += 1; k += 1
end
2 Likes
#5

What about using zip, like

for (i, j, k) in zip(1:10, 91:100, 991:1000)

(I had a typo in the c++ version, but the point is clear).
I don’t know how efficient “zip” is so I’m a little bit not decided on using it in this case.

And can you please add an ndigits method for a^b. Doing something like

ndigits(big(11111111111111)^1111111111111)

doesn’t work well since it seems to evaluate the expression first. So how about something like ndigits(a, b;base, pad).

#6

Julia always evaluates what it can as soon as it can. Additionally, your expression overflows what BigInt supports. So do not expect an ndigits version in Base Julia that will handle your example. Here is a way to get that information.

julia> using ArbNumerics, Readables

julia> ArbFloat("11111111111111")^ArbFloat("1111111111111")
3.296153757708430665985192510100e+14495286100621

julia> BigInt(ceil(log10(ans)))
14495286100622

julia> readable(ans)
14,495,286,100,622

as a macro:

using ArbNumerics

macro ndigitspow(base, power)
   :(BigInt(ceil(log10(ArbFloat(string($base))^ArbFloat(string($power))))))
end

# use it like this

julia> @ndigitspow(11111111111111,1111111111111)
14495286100622

julia> a = big"11111111111111"
11111111111111

julia> b = big"1111111111111"
1111111111111

julia> @ndigitspow(a,b)
14495286100622

julia> @ndigitspow(a,a)
144952861006229
1 Like
#7

Just benchmark it and see, but it depends on what you’re doing in the body of the loop whether zip incurs any overhead that matters. E.g. with a fairly simple body:

julia> using BenchmarkTools

julia> function f(x)
           s = 0
           for (i, j, k) in zip(1:10, 91:100, 991:1000)
               s += x[i] + x[j] + x[k]
           end
           return s
       end
f (generic function with 1 method)

julia> function g(x)
           s = 0
           i, j, k = 1, 91, 991
           while i <= 10
               s += x[i] + x[j] + x[k]
               i += 1
               j += 1
               k += 1
           end
           return s
       end
g (generic function with 1 method)

julia> x = rand(1000);

julia> @btime f($x)
  22.452 ns (0 allocations: 0 bytes)
14.075682753063184

julia> @btime g($x)
  8.369 ns (0 allocations: 0 bytes)
14.075682753063184