Ir ao conteúdo
  • Cadastre-se

C++ Salvar variável tipo double com numero limitado de casas decimais


Cortella

Posts recomendados

Boa noite,

 

Preciso desenvolver um programa que envolve resolução de sistemas lineares, porém preciso salvar as variáveis com 4 casas decimais para que no final gere um erro e atraves desse erro eu vou compara a eficiencia dos métodos.

Porém eu desenvolvi todo o programa e por considerar várias casas decimais o calculo é bem mais preciso do que deveria ser.

 

Gostaria de saber como fazer isso em c++;

 

Resumindo:

preciso que a atribuição:

double x = 3.66666666;

salve na variável x o valor = 3.6667;

 

OBS: O uso do setprecision() nao resolve o problema para mim , pois dessa forma ele apenas exibe na tela o valor arredondado, preciso que ele salve na variável o valor arredondado.

 

Obrigado!

  • Curtir 1
  • Triste 1
Link para o comentário
Compartilhar em outros sites

float alfa=3,456789;
float beta=0;
float cache=0;

cache=(alfa%0,0001)/10000;
beta=alfa-cache;

if (cache>=0.0005)
{
  beta=beta+0.0001;
}

fiz um script para teste só... mude os valores de 0,0001/0,0001/10000/0.0005 adicionando/tirando zeros para ajustes... alfa = antes de converter, beta = depois... cache é só para calculos mesmo, eu criei ela, mas dá pra fazer o calculo todo sem ela... mas com ela fica mais legivel o codigo... boa sorte :)

Link para o comentário
Compartilhar em outros sites

14 horas atrás, Cortella disse:

Gostaria de saber como fazer isso em c++;

 

Como fazer não muda quase nada em qualquer linguagem moderna porque em geral usam o mesmo formato de ponto flutuante IEEE 754 e sugiro ler algo a respeito.

 

Considere essa função

 

double doubleN( double original, unsigned d)
{
    double decimais = (double) d;
    double fator = pow( 10., -decimais);
    double res = original / fator;
    long long iDec = res;
    double resto = res - iDec; // subtrai a parte inteira
    if ( resto > .5 ) iDec += 1;
    res = (double) iDec * fator; // restaura o valor descartando o resto
    return res;
};

 

Em C ou C++ não faz diferença. Usar pow() é frescura e um atraso já que é um simples loop dividindo ou multiplicando por 10 afinal, e poderia ser
 

double doubleN( double original, unsigned d)
{
    double fator = 1.;
    for ( unsigned i = 0; i < d; i += 1) fator /= 10.;
    double res = original / fator;
    long long iDec = res;
    double resto = res - iDec;
    if ( resto > .5 ) iDec += 1;
    res = (double) iDec * fator;
    return res;
};

 

Como em C++ tem free-functions, aquelas funções soltinhas que não tem em java e que não estão em classe alguma, pode usar a mesma função nas duas linguagens.

 

Uma alternativa comum

 

É comum usar sprintf() e pegar o valor em modo string e depois usar strtod() e converter de volta. Nem vou mostrar um exemplo mas se achar preciso escreva de volta. Em tempos de pandemia e isolamento eu posso ter tempo afinal :D

 

O que doubleN() faz

 

O mesmo que o lápis: multiplica pelos dígitos da precisão desejada e subtrai a parte inteira. Se o resto for maior que 1/2 --- o popular 0,5 --- soma 1 na parte inteira e divide de volta pelo valor da precisão, efetivamente descartando o resto dos dígitos. 

 

Seria legal ver as diferenças e os erros acumulados ao diminuir a precisão... ;) então...

 

Considere o programa
 

int main(void)
{
    printf("\
Usando CONSTANTES e %%15.10f ==> [ 11/3 = %15.10f ] e [ 3.66667 = %15.10f ]\n",
        11./3.,
        3.66667
    );
    double teste = 11./3.;
    printf("\nUsando  uma  variavel para 11./3. ==>      %15.10f\n", teste);
    printf("Usando arredondamento (%%15.5f)    ==> %15.5f\n", teste);

    printf("\nUsando doubleN() para alguns valores\n");
    char mascara[80];
    for ( unsigned i = 1; i<10; i+=1)
    {
        double res = doubleN( teste, i );
        printf("\nValor original usando %%15.10f  ==>\t%15.10f\n", teste);
        printf("Usando doubleN(,%d)  %%15.10f   ==>\t%15.10f\n", i, res);
        sprintf( mascara, "Usando doubleN()  %%%%15.%df      ==>\t%%15.%df\n", i,i );
        printf( (const char*) mascara, res);
        printf("Valor residual = %15.10f\n", teste - res);
    }

    return 0;
}

 

Que vai mostrar

 

ch$  
ch$  gcc -o tst  -O3 -Wall mat.c
ch$  ./tst
Usando CONSTANTES e %15.10f ==> [ 11/3 =    3.6666666667 ] e [ 3.66667 =    3.6666700000 ]

Usando  uma  variavel para 11./3. ==>         3.6666666667
Usando arredondamento (%15.5f)    ==>         3.66667

Usando doubleN() para alguns valores

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,1)  %15.10f   ==>          3.7000000000
Usando doubleN()  %15.1f      ==>                   3.7
Valor residual =   -0.0333333333

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,2)  %15.10f   ==>          3.6700000000
Usando doubleN()  %15.2f      ==>                  3.67
Valor residual =   -0.0033333333

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,3)  %15.10f   ==>          3.6670000000
Usando doubleN()  %15.3f      ==>                 3.667
Valor residual =   -0.0003333333

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,4)  %15.10f   ==>          3.6667000000
Usando doubleN()  %15.4f      ==>                3.6667
Valor residual =   -0.0000333333

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,5)  %15.10f   ==>          3.6666700000
Usando doubleN()  %15.5f      ==>               3.66667
Valor residual =   -0.0000033333

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,6)  %15.10f   ==>          3.6666670000
Usando doubleN()  %15.6f      ==>              3.666667
Valor residual =   -0.0000003333

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,7)  %15.10f   ==>          3.6666667000
Usando doubleN()  %15.7f      ==>             3.6666667
Valor residual =   -0.0000000333

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,8)  %15.10f   ==>          3.6666666700
Usando doubleN()  %15.8f      ==>            3.66666667
Valor residual =   -0.0000000033

Valor original usando %15.10f  ==>         3.6666666667
Usando doubleN(,9)  %15.10f   ==>          3.6666666670
Usando doubleN()  %15.9f      ==>           3.666666667
Valor residual =   -0.0000000003

 

E pode acompanhar as diferenças usando entre 1 e 10 dígitos. E notar que é diferente imprimir uma constante 11/3 do que uma variável com o mesmo valor :) 

 

Não há nada de especial no programa exceto por um trecho um pouco raro de se ler onde o programa calcula o especificador para printf() em tempo de execução --- usando a irmã sprintf() --- para confirmar a precisão esperada:
 

        sprintf( mascara, "Usando doubleN()  %%%%15.%df      ==>\t%%15.%df\n", i,i );
        printf( (const char*) mascara, res);

 

Em C++ você usaria setw() de <iomanip> para o mesmo efeito

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!