Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Pulse

Erro com números/struct

Recommended Posts

Estou fazendo alguns testes usando scruct's, ponteiros, vetores de struct's e vetores de ponteiros com o código abaixo:

#include <stdio.h>

typedef struct{
    int idade;
    char sexo;
    int num_filhos;
    float salario;
} dados;

int main ()
{
    dados entrevistado[1];
    int i;
    float *salarios[1];

    printf("Salario:\n");
    scanf("%f", &entrevistado[0].salario);

    salarios[0] = &entrevistado[0].salario;

    printf("%f", *salarios[0]);
}

O problema é que ao entrar com um número o que é printado depois é uma aproximação dele e não o número exato. Como no caso:

 

jSnUgTk.png

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso se deve à representação dos números em ponto flutuante. A não ser que você use uma linguagem que tenha um tipo de dados de "precisão arbitrária" (decimal, no python, por exemplo), não há muito o que fazer.

Compartilhar este post


Link para o post
Compartilhar em outros sites
A rigor, não é erro de arredondamento. É método de arredondamento definido por padrões interagindo com implementações/arquitetura. O double também é afetado por isso.

Update 10/6/13: glibc printf() honors IEEE rounding mode
glibc printf() has been updated to take the current IEEE rounding mode into account. This was done in version 2.17; I just tested it on version 2.18. In doing it this way of course, round-to-nearest/round-half-away-from-zero is still not an option, so this doesn’t help you make its output consistent with other platforms.
C99, 7.19.6.1 (stdio.h, fprintf):

f,F A double argument representing a floating-point number is converted to decimal notation in the style [−]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is zero and the # flag is not specified, no decimal-point character appears. If a decimal-point character appears, at least one digit appears before it. The value is rounded to the appropriate number of digits.
Isso começa explicando porque o printf exibe os seis dígitos decimais. Ou seja, o que você vê na tela não é a precisão do tipo (p/ deixar as coisas claras).
#include <stdio.h>
#include <fenv.h>
int main(void) {
  float s;
  scanf("%f",&s);
  printf("rounding mode: to nearest: %f\n",s);
  fesetround(FE_DOWNWARD);
  printf("rounding mode: downards: %f\n",s);
  fesetround(FE_UPWARD);
  printf("rounding mode: upwards: %f\n",s);
  fesetround(FE_TOWARDZERO);
  printf("rounding mode: toward zero: %f\n",s);
  return 0;
}

isis@linux:~/src/imasters> ./a.out
99.99
rounding mode: to nearest: 99.989998
rounding mode: downards: 99.989997
rounding mode: upwards: 99.989998
rounding mode: toward zero: 99.989997
Se você colocar %.15f vai ter algo parecido com isso:

rounding mode: to nearest: 98.989997863769531 98.99
rounding mode: downards: 98.989997863769531 98.98
rounding mode: upwards: 98.989997863769532 98.99
rounding mode: toward zero: 98.989997863769531 98.98
Com %.30f já aparecem os zeros:

rounding mode: to nearest: 98.989997863769531250000000000000 98.99
rounding mode: downards: 98.989997863769531250000000000000 98.98
rounding mode: upwards: 98.989997863769531250000000000000 98.99
rounding mode: toward zero: 98.989997863769531250000000000000 98.98

For e, E, f, F, g, and G conversions, if the number of significant decimal digits is at most DECIMAL_DIG, then the result should be correctly rounded.240) If the number of significant decimal digits is more than DECIMAL_DIG but the source value is exactly representable with DECIMAL_DIG digits, then the result should be an exact representation with trailing zeros. Otherwise, the source value is bounded by two adjacent decimal strings L < U, both having DECIMAL_DIG significant digits; the value of the resultant decimal string D should satisfy L <= D <= U, with the extra stipulation that the error should have a correct sign for the current rounding direction.
...
240) For binary-to-decimal conversion, the result format’s values are the numbers representable with the given format specifier. The number of significant digits is determined by the format specifier, and in the case of fixed-point conversion by the source value as well.
Existe uma discussão que, fora os ataques de pelanca, é legal ler: https://sourceware.org/bugzilla/show_bug.cgi?id=4943
Basicamente a pessoa reclama que 2597.525000000000091 retorna 2597.53, mas 2597.625000000000000 retorna 2597.62 (ambos com o %.2f no printf). Suponho que ele queria que no primeiro caso o valor retornado fosse 2597.52.

Compartilhar este post


Link para o post
Compartilhar em outros sites
#include <stdio.h>



typedef struct{
    int idade;
    char o;
    int num_filhos;
    float salario;
} dados;


int main ()
{
    dados entrevistado[1];
    int i;
    float *salarios[1];
    
    printf("Salario:\n");
    scanf("%f", &entrevistado[0].salario);


    salarios[0] = &entrevistado[0].salario;


    printf("%.2f", *salarios[0]); //>>> Solucão

}

Post desnecessário

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.