Formatting multiple float values does not align when the number of digits is different

Asked

Viewed 86 times

-1

I am having formatting issues, due to the amount of data that appears on the screen, I try to insert the \t but is bugging. Follows image and code:

# Método da Falsa Posição - Cálculo Numérico
# Desenvolvido - Felipe Roque de Albuquerque Neto
# Instituto Federal de Pernambuco - Campus Recife
# Curso de Bacharelado em Engenharia Mecânica

#Importamos a biblioteca de matemática
import math 

# Definição dos intervalos [a,b]
a = float(input("Digite o valor de a: "))
b = int(input("Digite o valor de b: "))
print("\n")

# Definição da tolerancia
e = float(input("Digite o valor da tolerância desejada: "))
print("\n")

# Construção da Funçãa para entrada das equações
def f(x):
    return x**3-x-4 #Equação escolhida

print("a \t\t\t\tb   \t\t\t\tf(a)  \t\t\t\tf(b) \t\t\tXr  \t\t\t\tf(Xr)")
print("\n")
# Teoremo de Bolzano + Cálculo das iterações pelo método da Falsa posição
if(f(a)*f(b)) < 0:
    Xr = ((a*f(b))-(b*f(a)))/(f(b)-f(a))
    while(math.fabs(f(Xr)) > e):
        Xr = ((a*f(b))-(b*f(a)))/(f(b)-f(a))
        print("{} \t\t\t{} \t\t{} \t\t{} \t\t{}".format(a,b,f(a),f(b),Xr))
        if f(Xr) == 0:
            print("A raiz é: ".format(Xr))
        else:
            if f(Xr)*f(a) < 0:
                a = Xr
            else:
                b = Xr
    print("\n")
    print("Valor da raiz é: {}".format(Xr))
    print("\n")
else:
    print("Não há raiz no intervalo informado! Reveja seus dados!")

inserir a descrição da imagem aqui

2 answers

2


The problem of using \t is that if the size of the data varies, in fact its formatting may be "crooked". An alternative is to set a size to be occupied by each information, using the specific formats available.

For example, you could set a specific size that each column will occupy and align to the left:

size = 25 # cada coluna ocupará 25 espaços
print(("{:<{size}} " * 5).format("a", "b", "f(a)", "f(b)", "Xr", size=size))
...
if f(a) * f(b) < 0:
    Xr = ((a * f(b)) - (b * f(a))) / (f(b) - f(a))
    while math.fabs(f(Xr)) > e:
        Xr = ((a * f(b)) - (b * f(a))) / (f(b) - f(a))
        print(("{:<-{size}} " * 5).format(a, b, f(a), f(b), Xr, size=size))

The format for column names is {:<{size}}. The < indicates that the column will be aligned to the left, and the size indicates its size (in this case, it is 25).

I also made "{:<{size}} " * 5 to generate the string "{:<{size}} {:<{size}} {:<{size}} {:<{size}} {:<{size}} ", so it becomes easier to change the format, because you only need to change it once. Of course you could also write like this:

print("{:<{size}} {:<{size}} {:<{size}} {:<{size}} {:<{size}} ".format("a", "b", "f(a)", "f(b)", "Xr", size=25))

But if you need to change the format of the columns (for example, if you want to align to the right, you have to change the < for >), will have to do it 5 times. So if the format is the same for all columns, I think it pays to do the first way ("{:<{size}} " * 5).

In the case of numbers (within the while), I also use - in the format, which indicates that the sign should be printed only for negative numbers. And just like I did for the column names, they occupy 25 spaces and are aligned to the left.

The way out is like this:

a                         b                         f(a)                      f(b)                      Xr                        


-2.5123456789012346       30                        -17.34528080057978        26966                     -2.491446277458697        
-2.5123456789012346       -2.491446277458697        -17.34528080057978        -16.973719545318616       -1.536716542515489        
-2.5123456789012346       -1.536716542515489        -17.34528080057978        -6.092236087424354        -1.008525001102407        
-2.5123456789012346       -1.008525001102407        -17.34528080057978        -4.017268648696145        -0.5552502296408267       
-2.5123456789012346       -0.5552502296408267       -17.34528080057978        -3.615934980583952        -0.03980470236627769      
-2.5123456789012346       -0.03980470236627769      -17.34528080057978        -3.9602583647745715       0.6917518662933995        
-2.5123456789012346       0.6917518662933995        -17.34528080057978        -4.360734317386491        1.7678170288055575        
-2.5123456789012346       1.7678170288055575        -17.34528080057978        -0.24307582649463333      1.8286515287594436        
1.8286515287594436        1.7678170288055575        0.2862977656530621        -0.24307582649463333      1.7957507916056346        

Obviously, if the numbers are so large that they take up more than 25 spaces, the solution would be to increase the size and/or limit decimal places (which has already been commented on in another answer).


Other option

The solution below is just a curiosity, as it is preferable to use the options available on format (see at documentation that there are many other options to control formatting, which is better than trying to manually tweak with spaces and tabs).

Anyway, it is possible to change the "size" of a \t, using the method expandtabs. Then simply change it to a size that is sufficient to contain all the numbers, thus avoiding the misaligned columns:

size = 25
print("a\tb\tf(a)\tf(b)\tXr".expandtabs(size))
...
if f(a) * f(b) < 0:
    Xr = ((a * f(b)) - (b * f(a))) / (f(b) - f(a))
    while math.fabs(f(Xr)) > e:
        Xr = ((a * f(b)) - (b * f(a))) / (f(b) - f(a))
        print(("{}\t" * 5).format(a, b, f(a), f(b), Xr).expandtabs(size))

Thus, each \t will have the specified size (in case, 25), and the output is similar to the previous example.

But I still find it better to use the specific formats that the format makes available, as they are more powerful and flexible, and less prone to errors compared to manual formatting.

  • Boy, I didn’t know that one existed < in format. Very good the answer, but testing this I realized that using < does not limit the value size, it only adds spaces if necessary. So how would you do if the value was greater than 10 for example ?

  • @Jeanextreme002 In the test I did (see the output above) has values greater than 10 (30 e 26966). I did not understand your question... Anyway, you can also combine the < with .3f, if I’m not mistaken, then you have a very complete control over the format...

  • What I mean is that for everything to be formatted, the strings need to be the same size, but when running this for example "{:<10}".format("string com o tamanho maior que 10"), we can see that the string will not have size 10 because < serves only to add spaces but not limit the string to a size of 10 understands ?

  • @Jeanextreme002 Yes, there is not much magic, you have to check the size of the columns you are working and choose a suitable size that fits. The same is true if we limit the number of decimals, as stated at the end of your reply. In the end, both of our answers will have similar problems, depending on the data and the chosen size.

1

The character \t works perfectly, what happens is that the data can have different sizes and the spacing should suit this difference. What you can do there is create a code to set a fixed size for the data, so that the empty spaces of the string are occupied by space characters (" "). Example:

tamanho = 25
string = "2.343"
string_formatada = string + (" " * (tamanho - len(string)))

There is another simpler way and maybe it is the best one in your case that is setting zeros after the value. To do this use inside the keys :.<num>f to add zeros after floating point. See below for an example:

valor = 2.345354
string_formatada = "{:.10f}".format(valor)  # 2.3453540000

The problem with this type of formatting is that if the number is larger than the size you set, it may lose its accuracy. Also, this format limits numbers only after the floating point. So if the number is 273.35 and I limit the value only by decimals, the final size of the data may not be as expected. Example:

# No exemplo, eu quero que dado tenha um tamanho de 5 caracteres.

valor = 273.45
string_formatada = "{:.3f}".format(valor)

# O tamanho é 7 pois há 3 caracteres antes do ponto 
# quando o esperado era ter somente um caractere antes.
print(len(string_formatada))
  • um, got it. I’ll test out those tips of yours, thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.