How can I make Julia output vectors as pretty as Numpy?
Asked Answered
B

3

7

If I do the following:

A = [
  2   1   3   0   0;
  1   1   2   0   0;
  0   6   0   2   1;
  6   0   0   1   1;
  0   0 -20   3   2
]
b = [10; 8; 0; 0; 0]
println(A\b)

The output is:

[8.000000000000002, 12.0, -6.000000000000001, -23.999999999999975, -24.000000000000043]

However, I would prefer it look similar to the way Numpy outputs the result of the same problem (EDIT: preferably keeping a trailing zero and the commas, though):

[  8.  12.  -6. -24. -24.]

Is there an easy way to do this? I could write my own function to do this, of course, but it would be pretty sweet if I could just set some formatting flag instead.

Thanks!

Berthold answered 1/2, 2023 at 7:43 Comment(2)
Do you mean that you want the println function to show this format, or the automatic REPL display? BTW, I recommend, the format [8.0, 12.0, ...] over [8. 12. ...]. Firstly, omitting decimal zeros is a bad habit, that makes numbers less readable (and is ugly, imo). Secondly, you need the commas in there, because without them it is a different data structure, 1xN matrix instead of N-vector. It's important to show the correct data type.Lumberyard
@Lumberyard I agree, omitting decimal zeros is ugly, and it's better to have commas. I wrote this question at almost 2am last night, so I failed to consider those details. As for your first question, I'm asking for the println function to show this. I prefer running scripts over REPL. To me, exact repeatability is too hard to let go of. If I make a mistake in a script, I fix it. If if make a mistake in REPL, I have to repeat the entire process!Berthold
L
9

The standard way to do it is to change the IOContext:

julia> println(IOContext(stdout, :compact=>true), A\b)
[8.0, 12.0, -6.0, -24.0, -24.0]

You can write your function e.g. (I am not trying to be fully general here, but rather show you the idea):

printlnc(x) = println(IOContext(stdout, :compact=>true), x)

and then just call prinlnc in your code.

Liberati answered 1/2, 2023 at 11:45 Comment(1)
Splendid! This is exactly what I wanted. I was tired when I wrote the question, and failed to mention that I would indeed prefer the zeroes and commas to be shown. Your answer read my mind!Berthold
I
2

You could change the REPL behavior in Julia by overriding the Base.show method for floats. For an example:

Base.show(io::IO, f::Float64) = print(io, rstrip(string(round(f, digits=7)),'0') )

Now you have:

julia> println(A\b)
[8., 12., -6., -24., -24.]

As noted by @DNF Julia is using commas in vectors. If you want to have a horizontal vector (which is a 1xn matrix in fact) you would need to transpose:

julia> (A\b)'
1×5 adjoint(::Vector{Float64}) with eltype Float64:
 8.  12.  -6.  -24.  -24.

julia> println((A\b)')
[8. 12. -6. -24. -24.]
Irremissible answered 1/2, 2023 at 11:22 Comment(1)
Typically overwriting Base.show definition for standard types like Float64 is not recommended.Ljubljana
S
2

Numpy lies to you. It just hides the digits when printing. To check that it only manipulates the printing of the output, do print(A @ X - b) and see the result.

print(A @ X - b)
[ 0.00000000e+00  0.00000000e+00  0.00000000e+00 -3.55271368e-15  0.00000000e+00]

Julia, on the other hand, makes this clear upfront. If you do the same in Julia, you get the same result (I use Foat64 as Numpy does):

julia> X = A \ b;

julia> Float64.(A) * X - b
5-element Vector{Float64}:
  0.0
  0.0
  0.0
 -3.552713678800501e-15
  0.0

You can use compact printing, however, similar to arrays to remove the unnecassary digits.

julia> round.(X, digits=7)
5-element Vector{Float64}:
   8.0
  12.0
  -6.0
 -24.0
 -24.0

This, is much better than the "ugly" 8. 12. -6. -24. -24.

Synaesthesia answered 1/2, 2023 at 19:24 Comment(1)
This is an equally good solution! Thank you for teaching me that the round function can be used element-wise when a dot is appended.Berthold

© 2022 - 2024 — McMap. All rights reserved.