float - Como obter precisão com esses tipos?

328 views
Skip to first unread message

wishmaster_rs

unread,
May 14, 2006, 5:35:55 PM5/14/06
to ccppbrasil
Para desenvolver aplicações financeiras, como fazer com que números
float tenham precisão? É drástico ver que o resultado de seu
cálculo aparece como 199,00, quando deveria aparecer como 198,99.

wishmaster_rs

unread,
May 14, 2006, 5:38:25 PM5/14/06
to ccppbrasil

DQ

unread,
May 14, 2006, 6:55:19 PM5/14/06
to ccppbrasil
Para aplicações financeiras NÃO deve ser usado os números float. O
formato destes números não é capaz de representar precisamente todos
os números decimais (pois os guarda como a soma de frações binárias
1/2 1/4 1/8 etc).

Para aplicações financeiras, devem ser usados tipos inteiros (quando
fornecerem um número suficiente de dígitos, o que não é comum) ou
formatos que armazem os dígitos individualmente. O mais comum deste
segundo tipo é o BCD (binary coded decimal), onde cada dígito decimal
é armazenado em 4 bits (o que permite compactá-los na forma de dois
dígitos por byte).

Infelizmente o C e o C++ não tem este tipo nativo.

Este é mais um motivo da sobrevivência do Cobol ; )

wishmaster_rs

unread,
May 14, 2006, 8:09:39 PM5/14/06
to ccppbrasil
Quando eu preciso de precisão numérica em aplicações C++ (estou
falando de C++ apenas), como eu devo proceder? Uma divisão de dois
núemros em formato double retorna um número decimal, mas, qual a
precisão desse número? Isso está um pouco confuso para mim. Até
onde eu posso confiar nesse número?

Rodrigo Strauss

unread,
May 14, 2006, 8:29:45 PM5/14/06
to ccppb...@googlegroups.com
Eu não sabia desse formato do COBOL... Onde eu trabalho, toda ver que
recebemos número do mainframe, vem o número e logo depois qual a
posição da vírgula nesse número.

wishmaster_rs

unread,
May 14, 2006, 10:21:31 PM5/14/06
to ccppbrasil
Rodrigo, não entendi o teu comentário... De qualquer jeito, como
obter precisão numérica em C++? Eu gostaria de exemplos matemáticos
de quando eu posso confiar no resultado e de quando eu NÃO posso
confiar no resultado.

Obrigado a todos!

DQ

unread,
May 15, 2006, 7:15:32 AM5/15/06
to ccppbrasil
Indo por partes:

Números float e double são armazenados em duas partes: a mantissa
(que é o valor em si) o expoente (que indica onde fica a vírgula).
Na representação decimal (base 10), cada dígito vale 10 vezes mais
que o dígito a sua direita e 10 vezes menos que o dígito a sua
esquerda. Por exemplo: 0,13 decimal corresponde a 0 + 1/10 + 3/100. Os
números float e double armazenam a mantissa em binário, onde cada
dígito vale 2 vezes mais que o dígito a sua direita e 2 vezes menos
que o dígito a sua esquerda. Por exemplo 0,001 binário corresponde a
0 + 0/2 + 0/4 + 1/8 = 0,125. Repare que existem números que podem ser
representados com uma certa quantidade de dígitos decimais mas não
podem ser representados precisamente com um número finito de dígitos
binários. Portanto, respondendo a sua pergunta de como obter precisão
usando float e double, a resposta é que não é possível.

Maiores detalhes sobre float e double em
http://www.codeguru.com/forum/printthread.php?t=323835

A solução é usar uma classe ou biblioteca que armazene os números
em formato BCD. Dei uma procurada rápida e infelizmente não achei
muita coisa.. talvez algum dos colegas possa indicar algo.

Rodrigo Strauss

unread,
May 15, 2006, 8:37:39 AM5/15/06
to ccppb...@googlegroups.com
Para ter precisão maior você precisa de uma biblioteca separada. Dê
uma olhada em http://www.google.com/search?q=bignum

Rodrigo Strauss

Thiago Adams

unread,
May 15, 2006, 11:06:45 AM5/15/06
to ccppbrasil
"Para desenvolver aplicações financeiras, como fazer com que números

float tenham precisão? É drástico ver que o resultado de seu
cálculo aparece como 199,00, quando deveria aparecer como 198,99. "

Que cáculo você fez e como você mostrou o resultado na tela?
Este erro parece muito grande para ser devido aos seus calculos,
provalmente foi arredondado na hora de mostrar.

DQ

unread,
May 15, 2006, 11:21:01 AM5/15/06
to ccppbrasil
Achei algo que talvez seja útil:

http://www2.hursley.ibm.com/decimal/

A biblioteca decNumber parece fazer o que você precisa.

wishmaster_rs

unread,
May 15, 2006, 11:51:32 AM5/15/06
to ccppbrasil
Não, grande Thiago, esse exemplo que eu dei foi apenas um exemplo,
não aconteceu de verdade. Não obtive essa saída de nenhum programa.
Mas por exemplo, você sabe calcular juros compostos?

montante = C * (1 + i ) ^ n

C = Capital
i = Taxa de juros
n = períodos

Quero investir R$ 856,50 durante 9 meses em CDB porque tá rendendo 18%
ao ano. Ah, eu uso juros compostos:

856.50 * ( 1 + (0.18 / 12 ) ) ^ 9 = Vamos fazer esse cálculo na mão,
com o lápis e o papel:

0.18 / 12 = 18 / 1200 << Iguala o número de casas depois da
vírgula....
18 é divisível por 1200? Não. então, coloca um 0, uma vírgula e
mais um zero.
1800 / 1200 = 0,0????
1800 é divisível por 1200? Sim.
1800 / 1200 = 0,01 com resto 600. Coloca mais um zero no resto.
6000 / 1200 = 0,015 << Nossa taxa mensal !

856.50 * ( 1 + 0,015) ^ 9 =

856.50 * (1,015) ^ 9 =

856.50 * 1,143389975 = <<< Olha o tamanho do número da taxa de
juros!!! Em C++, minha taxa de juros já tava detonada... pelo menos
com o conhecimento que eu tenho.

Montante = 979.3135139 ou seja: R$ 979,31 centavos. << Talvez o meu
montante tenha sido detonado pelo C++ também (com o conhecimento que
eu tenho, lógico)

Como esses números em C++ seriam tratados?

E se o capital fosse R$ 2.356.287.33, o período fosse 24 meses e a
taxa anual fosse 22,359% ao ano?

Um dos meus planos é desenvolver uma pequena aplicação financeira.
Preciso saber como vou tratar meus números ou então podemos resumir o
assunto se, em C++, não for possível obter precisão com moeda.

Rodrigo Strauss

unread,
May 15, 2006, 1:27:38 PM5/15/06
to ccppb...@googlegroups.com

wishmaster_rs

unread,
May 15, 2006, 1:52:52 PM5/15/06
to ccppbrasil
DQ,

A biblioteca decNumber parece bem interessante. Vou dar uma olhadinha
de perto.

Valeu!

Rodrigo, o tópico sobre o assunto é bom. Muito obrigado!

Thiago Adams

unread,
May 15, 2006, 4:03:19 PM5/15/06
to ccppbrasil
Dá uma olhadinha no exemplo abaixo. Tem precisão suficiente na minha
opnião.

#include <cmath>
#include <iostream>
#inlcude <limits>

using namespace std;

inline double Fator(double i, int n)
{
return pow(1 + i, n);
}

int main()
{
cout.precision( numeric_limits<double>::digits10 );
{
double PV = 856.50;
double taxa_ano = 0.18 / 12.0;
int n = 8; //meses
cout << fixed << PV * Fator(taxa_ano, n) << endl;
}
}

Este programa que você quer fazer é um ótimo programa para aprender
C++.
O interessante deste problema dos juros é tentar calular o "i" dado as
outras variáveis. :)
Talvez a implementação da função pow que você esteja usando seja
diferente da que é usada no VC++.

Saída do programa:
964.840900418879300


Quando você aprender classes vai ser interessante criar uma para
representar moeda.

wishmaster_rs

unread,
May 15, 2006, 4:20:43 PM5/15/06
to ccppbrasil
Ainda estou usando o Devian Bloodshed. A função pow ( x , y ) usa
números em formato double. Números em formatos inferiores são
"promovidos" a double e, depois do cálculo efetuado, tornam a ser o
que eram antes. No meu caso, eu já estou usando double em todas as
variáveis de taxas, juros, montantes, moedas, etc etc e etc, exceto
variáveis q não calculam a grana: contadores e etc.

Agora, me diz uma coisa:

( numeric_limits<double>::digits10 ); <<< Esse parâmetro está
limitando o quê? Todo o número? Só os dígitos decimais? Ainda não
conheço essa função. PeloAmorDeDeus, o que é isso?

Vou postar aqui o meu "protótipo de programa" e vocês poderão dar
uma analisada. Ele foi desenvolvido com o conhecimento obtido até
agora, então, tenham paciência, ok?

Muito obrigado Thiago e
um grande abraço a todos!

Thiago Adams

unread,
May 15, 2006, 4:57:13 PM5/15/06
to ccppbrasil
( numeric_limits<double>::digits10 ); Não te preocupa com isso.
Olha isso mais adiante.
O que aquela linha faz é mostrar todas as casas que o double tem
precisao na formatação do cout.
Poderia escrever um numero ali.

Poderia te passar a implementacao da pow.. mas acho melhor vc conseguir
um vc++ express.

wishmaster_rs

unread,
May 15, 2006, 8:13:29 PM5/15/06
to ccppbrasil
Grande Thiago Adams (dã dã dã dã, tlac tlac, dã dã dã dã, tlac
tlac)

Aqui está o código. Vale salientar que a questão aqui é a precisão
dos cálculos, e não dos "serviços bancários :DD" que o programa
poderia oferecer. Interessante é compilar o programa e executar para
familiarizar-se com a questão.
Na verdade, eu não sei se a saída do meu programa são números
precisos....

As variáveis meses e n estão em double porque alguém vai digitar um
investimento durante 3.54 meses, o que não é errado se o tempo de
investimento for de 106 dias, 4 horas e 48 minutos... mas vai saber,
né? (Um mês comercial tem 30 dias)

/*
Brincando de Investimento
Cada investimento é uma operação separada das demais
O resumo final é um balanço geral
wishinvest.cpp
*/

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

#include <cmath>
#include <iomanip>

using std::setprecision;

double cdb ( double, double, double );

int main ( )
{
double c,
i,
mont,
conta = 0,
n,
todocap,
meses;


cout << "Vamos brincar de banco de investimento\n"
<< "Insira o valor do investimento: ";
cin >> c;
todocap =c;
cout << "Insira a taxa de juros anual SEM o simbolo %: ";
cin >> i;
cout << "Informe o periodo do investimento em meses: ";
cin >> n;
meses = n;


cout << "Seu montante: "
<< setprecision(12);
mont = cdb (c, i, n);
conta += mont;
cout << mont << endl << endl;

int sn =1 , cont = 1;

while ( sn == 1){
cout << "Realizar outro investimento? (1) sim (2) nao\n";
cin >> sn;
if (sn == 1){
cont++;
cout << "Investimento: ";
cin >> c;
todocap += c;
cout << "Taxa de juros anual: ";
cin >> i;
cout << "periodo do investimento (meses): ";
cin >> n;
meses += n;
mont = cdb (c, i, n);
conta += mont;
cout << "Seu montante: " << mont << endl
<< "Investimento n: " << cont << endl;
}
}

cout << "\nVoce investiu ao todo " << todocap
<< "\ne obteve " << conta << " o que equivale a um juro\n"
<< "total de " << setprecision(5)
<< ((conta/todocap)-1)*100 << " por cento, depois de" <<
endl
<< meses << " meses de investimento total."
<< endl << endl;


system("PAUSE");
return 0;
}

double cdb (double a, double b, double c )
{
return a * pow(((1+((b/100)/12))), c);
}

Thiago Adams

unread,
May 16, 2006, 4:50:47 PM5/16/06
to ccppbrasil
Fiz um programinha no console, do tipo que a muito tempo não fazia. :)

vou colocar o codigo aqui:

#ifndef CONSOLE_HEADER
#define CONSOLE_HEADER

namespace console
{
enum Color
{
Black,
Gray ,
Blue,
LightBlue,
Green ,
LightGreen,
Aqua ,
LightAqua,
Red ,
LightRed,
Purple ,
LightPurple,
Yellow ,
LightYellow,
White ,
BrightWhite
};


void gotoxy(int x, int y);
void clear();
int get_key();
void put_color(Color fore, Color back);
}

#endif
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


#include "console.h"
#include <windows.h>
#include <conio.h>


int console::get_key()
{
return (int) _getwch();
}

void console::gotoxy(int x, int y)
{
COORD point;
point.X = (SHORT) x;
point.Y = (SHORT) y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point);
}

void console::clear()
{
COORD coordScreen = { 0, 0 };
unsigned long cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
unsigned long dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}

void console::put_color(Color fore, Color back)
{
WORD wColor = 0;

switch (fore)
{
case Black: wColor |= 0;break;
case Gray: wColor |= FOREGROUND_INTENSITY; break;
case Blue: wColor |= FOREGROUND_BLUE;break;
case LightBlue: wColor |= FOREGROUND_BLUE | FOREGROUND_INTENSITY;
break;
case Green: wColor |= FOREGROUND_GREEN; break;
case LightGreen: wColor |= FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break;
case Aqua: wColor |= FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case LightAqua: wColor |= FOREGROUND_GREEN | FOREGROUND_BLUE|
FOREGROUND_INTENSITY;break;
case Red: wColor |= FOREGROUND_RED; break;
case LightRed: wColor |= FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
case Purple: wColor |= FOREGROUND_RED | FOREGROUND_GREEN; break;
case LightPurple: wColor |= FOREGROUND_RED | FOREGROUND_BLUE |
FOREGROUND_INTENSITY; break;
case Yellow : break;
case LightYellow: break;
case White: wColor |= FOREGROUND_RED | FOREGROUND_GREEN |
FOREGROUND_BLUE; break;
case BrightWhite: wColor |= FOREGROUND_RED | FOREGROUND_GREEN |
FOREGROUND_BLUE | FOREGROUND_INTENSITY; break;
}

switch (back)
{
case Black: wColor |= 0;break;
case Gray: wColor |= BACKGROUND_INTENSITY; break;
case Blue: wColor |= BACKGROUND_BLUE;break;
case LightBlue: wColor |= BACKGROUND_BLUE| BACKGROUND_INTENSITY;
break;
case Green: wColor |= BACKGROUND_GREEN; break;
case LightGreen: wColor |= BACKGROUND_GREEN| BACKGROUND_INTENSITY;
break;
case Aqua: wColor |= BACKGROUND_GREEN | BACKGROUND_BLUE;
break;
case LightAqua: wColor |= BACKGROUND_GREEN | BACKGROUND_BLUE|
BACKGROUND_INTENSITY;break;
case Red: wColor |= BACKGROUND_RED; break;
case LightRed: wColor |= BACKGROUND_RED| BACKGROUND_INTENSITY;
break;
case Purple: wColor |= BACKGROUND_RED | BACKGROUND_GREEN; break;
case LightPurple: wColor |= BACKGROUND_RED | BACKGROUND_BLUE|
BACKGROUND_INTENSITY; break;
case Yellow : break;
case LightYellow: break;
case White: wColor |= BACKGROUND_RED | BACKGROUND_GREEN |
BACKGROUND_BLUE; break;
case BrightWhite: wColor |= BACKGROUND_RED | BACKGROUND_GREEN |
BACKGROUND_BLUE | BACKGROUND_INTENSITY; break;
}

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor);
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include "console.h"


using namespace std;
using namespace console;


struct InColor
{
const char * const text;
console::Color color;
InColor(console::Color c, const char *t ) : text(t), color(c){}
friend ostream & operator << (ostream &i, const InColor &o)
{
put_color(o.color, console::Black);
i << o.text;
put_color(console::White, console::Black);
return i;
}
};

template<class T>
void GetValue(const char * tag, T & value, int col, int &row)
{
const int w = 37;
const int r = row++;
gotoxy(col, r);
cout.width(w);
cout << InColor(White, tag);
cin.clear(); //nao sei pq mas não esta se recuperand, talvez seja
devido as funcoes de consle
cin >> value;
bool ok = !cin.fail();
console:Color color = ok ? Gray : Red;
gotoxy(col, r);
cout.width(w);
cout << InColor(color, tag);
}

void Header(int col, int &row)
{
gotoxy(col, row);
cout << InColor(LightGreen, "Programa de investimentos");
row += 2;
}

bool ExitQuestion(int col, int & row)
{
row += 2;
gotoxy(col, row);
cout << "Deseja continuar? "
<< InColor(White,"S") << InColor(Gray, "im")
<< InColor(White," N") << InColor(Gray, "ao");
int i = get_key();
return (i == 's') || (i == 'S');
}

void InputScreen(double &investimento,
int &taxa,
int &periodo,
int col, int &row)
{
cin.clear();
row++;
GetValue("Investimeto (R$): ", investimento, col, row);
GetValue("Taxa de juros (periodo) (0% - 100%): ", taxa, col, row);
GetValue("Num. periodos : ", periodo, col, row);
row +=2;
}

void OutputScreen(double investimento,
int taxa,
int periodo,
int col, int &row)
{
double taxajuros = (double(taxa) / 100.0) / 1.0; //1 perido

row++;
gotoxy(col, row);
cout << "Valor futuro : " << investimento * std::pow(1 + taxajuros,
periodo);
row += 2;
}

int main ( )
{
for(;;)
{
int col = 2, row = 2;
double investimento;
int taxa;
int periodo;

console::clear();
Header(col, row);
InputScreen(investimento , taxa, periodo, col, row);
OutputScreen(investimento , taxa, periodo, col, row);

if (!ExitQuestion(col, row))
break;
}
}

O interessante é que o cin.clear não funcionou como eu esperava, e
não deixou o cin pronto para o proximo valor.
Ficou que o programa não se recupera mais depois de um erro.

Thiago Adams

unread,
May 16, 2006, 4:51:19 PM5/16/06
to ccppbrasil

wishmaster_rs

unread,
May 16, 2006, 5:47:35 PM5/16/06
to ccppbrasil
Não entendi....

Thiago Adams

unread,
May 16, 2006, 6:59:12 PM5/16/06
to ccppbrasil
coloquei o programa mais por curiosidade.
Se alguem quiser ver como limpar a tela no console, ou como posicionar
o cursor essas coisas..tem ali.

Algumas coisas são basicas e imporantes. Já leu sobre referecencias
no c++?
sobre namespaces é bom dar uma lida tb. Notei que você costuma
colocar using item por item. Apesar de ser mais preciso, costuma-se
fazer isso apenas quando existe um conflito especifico, caso contrario
se coloca o namespace todo. por ex. using namespace std;
Não se preocupe se não entendeu tudo neste momento.

wishmaster_rs

unread,
May 16, 2006, 10:19:32 PM5/16/06
to ccppbrasil
Cara, sobre o using, eu coloco apenas o que eu uso, assim como
mostra no livro. Acho que mais adiante eles ensinam como usar melhor
isso...
na verdade, eu acho um SACO digitar cada um dos ítens que eu vou
usar....
Mais adiante no livro tem coisas sobre namespaces. Estou na fase de
exercícios
finais do capítulo 3, que introduz o coneito de função, escopo de
função, função recursiva e tals...
o Capítulo 4 introduz o conceito de arrays. Até o capítulo 6 é tudo
o básico,
depois, o negócio fica pesado!

Cara, eu queria muito executar o teu programa, mas não compilou
aqui... deve ser porque eu tô com Dev C++ ainda.

As referências q que vc se refere seria função por referência?
Variável por referância (alias)? Se não, eu acho que tô meio
confuso....


Eu queria mais informações disso que vc falou sobre o using.

Leonardo Stabile

unread,
May 16, 2006, 10:56:37 PM5/16/06
to ccppbrasil
toda a biblioteca padrão do C++ está no namespace "std", por isso
você utiliza std::cout, std::fstream, std::list, ...você pode
declarar a utilização desses elementos no seu módulo item a item,
como os códigos que você escreveu anteriormente, mas você também
pode declarar que vai utilizar TODO o namespace std:

using namespace std;

dessa maneira, sempre que você escrever cout no código, na
compilação será procurado "cout" por todo o namespace std. Fica mais
fácil escrever o código assim pois fica subentendido que o std será
utilizado.

Como nem tudo na vida é maravilha existem as exceções: suponha que
você está utilizando duas libs, uma pra sockets e outra pra interface
gráfica, que ambas ofereçam tratamento próprio de exceção e que
ambas chamaram a função que lança um exceção de exception(). Se em
algum módulo você utilizar as duas e escrever:

using namespace lib_grafica;
using namespace lib_socket;

ao utilizar "exception()" no módulo, o compilador não saberá qual
das duas usar. Pra resolver isso você faz a declaração item a item,
como acima, ou instancia explicitamente a função que você realmente
quer:

lib_grafica::exception()

Seria melhor você ler antes o capítulo sobre namespaces senão fica
difícil entender mesmo...

Quanto a não ter compilado deve ser por causa da conio, eu falei no
outro topico pra ficar longe dela ehe... se você usar o VC++
provavelmente funcionará.

Abraços

Thiago Adams

unread,
May 17, 2006, 4:48:32 AM5/17/06
to ccppbrasil
Diga-me que erro está ocorrendo.
É um programa para windows. Tem "window.h" e o "conio.h"?
Se voce instalar o express eu te passo o projeto.

--------------
Para o pessoal do wiki.
Acho que uma boa ajuda para os iniciante seria n'os colocarmos links e
escrever de como instalar o vc++ express. (Existem filmes da MS para
download explicando tudo at'e como configurar a SDK)
Nao sei tamb'em se tem gente interessada.

Rodrigo Strauss

unread,
May 17, 2006, 8:03:28 AM5/17/06
to ccppb...@googlegroups.com
pequena correção: é "windows.h"

A instalação é next>>next>>finish, acho que seria necessário dizer
onde baixar e como configurar para usar o SDK

Leonardo Valiante

unread,
May 17, 2006, 8:09:35 AM5/17/06
to ccppb...@googlegroups.com
Fala aê Thiago!!
 
Gostei do programinha no console, mas achei vários "bugzinhos"...
 
Será que é porque eu uso o MSVS6??
 
Bem...
Alguns deles foram:
faltou o "return 0;" no final de main
faltou declarar o "include <cmath>"
a comando "pow" não faz parte do std (estava std::pow)
vc usou uma função que eu acho que não existe "_getwch()" não seria "getch()"?
 
E outras frescurinhas mais....
 
No seu compilador não foram acusados esses erros???
 
um abraço,
 
Leonardo Valiante

 
2006/5/16, Thiago Adams <thiago...@gmail.com>:
--
Leonardo Valiante

Hugo Parente Lima

unread,
May 17, 2006, 8:56:05 AM5/17/06
to ccppb...@googlegroups.com
Em Quarta 17 Maio 2006 09:09, Leonardo Valiante escreveu:
> Fala aê Thiago!!
>
> Gostei do programinha no console, mas achei vários "bugzinhos"...
>
> Será que é porque eu uso o MSVS6??
>
> Bem...
> Alguns deles foram:
> faltou o "return 0;" no final de main

A função main não precisa ter o "return INT"... caso seja omitido o compilador
considera "return 0;" mas isso SÓ VALE para a função main()... e que de
qualquer modo PRECISA ter INT como valor de retorno em sua declaração (nada
de void main()).

> faltou declarar o "include <cmath>"
> a comando "pow" não faz parte do std (estava std::pow)

Tem um std::pow em <complex> se não me engano =]
Me corrijam se eu estiver errado... mas quando você usa #include <cmath> ele
inclui o cabeçalho do math.h do C, só que no namespace std.

> vc usou uma função que eu acho que não existe "_getwch()" não seria
> "getch()"?
> E outras frescurinhas mais....
>
> No seu compilador não foram acusados esses erros???
>
> um abraço,
>
> Leonardo Valiante

--
Hugo Parente Lima.
"Precisamos de mais gênios humildes no mundo, hoje somos poucos!"
JID: hu...@jabber.org

Rodrigo Strauss

unread,
May 17, 2006, 9:10:56 AM5/17/06
to ccppb...@googlegroups.com
> A função main não precisa ter o "return INT"... caso seja omitido o compilador
> considera "return 0;" mas isso SÓ VALE para a função main()... e que de
> qualquer modo PRECISA ter INT como valor de retorno em sua declaração (nada
> de void main()).

Pelo padrão C++ ISO *precisa* retornar int, não é implícito. Se for C,
aí não precisa, o padrão ANSI não exige.

Sobre os outros detalhes, lembrem-se que o Visual C++ 6 é péssimo
quando se fala em padrão ISO, algumas coisas podem ser diferentes
nele:

http://www.1bit.com.br/content.1bit/weblog/vc6_is_tooo_old

O que escrevi nesse post sobre o VC 7 e 7.1 vale para o VC8, que é o
compilador VCExpress.

Wanderley Caloni Jr

unread,
May 17, 2006, 9:52:06 AM5/17/06
to ccppb...@googlegroups.com
Acredito que o detalhe sobre o "return 0;" que o Hugo se referia está
no padrão C++, que admite o retorno implícito do valor 0 caso não haja
um retorno explícito. Isso só vale para C++ e só para o main. Não é o
detalhe sobre o _tipo_ de retorno, onde C++ é enfático enquanto a
linguagem C ainda é permissiva (com razão, dada a quantidade de código
legado).

Mas não recomendo o uso desse artifício do padrão. Você estará usando
algo que só é válido em C++ (não em C), confunde os que não conhecem
esse detalhe insignificante e, por fim, só é válido para a função
main. Não é porque estamos usando uma linguagem complexa que não
podemos usar o método KIS =)

[]s


--
Wanderley Caloni Jr
http://www.caloni.com.br

Hugo Parente Lima

unread,
May 17, 2006, 11:51:08 AM5/17/06
to ccppb...@googlegroups.com
On 5/17/06, Wanderley Caloni Jr <wanderl...@gmail.com> wrote:
>
> Acredito que o detalhe sobre o "return 0;" que o Hugo se referia está
> no padrão C++, que admite o retorno implícito do valor 0 caso não haja
> um retorno explícito. Isso só vale para C++ e só para o main. Não é o
> detalhe sobre o _tipo_ de retorno, onde C++ é enfático enquanto a
> linguagem C ainda é permissiva (com razão, dada a quantidade de código
> legado).

Exato.

> Mas não recomendo o uso desse artifício do padrão. Você estará usando
> algo que só é válido em C++ (não em C), confunde os que não conhecem
> esse detalhe insignificante e, por fim, só é válido para a função
> main. Não é porque estamos usando uma linguagem complexa que não
> podemos usar o método KIS =)

Também concordo.

--
Hugo Parente Lima

Thiago Adams

unread,
May 17, 2006, 1:31:12 PM5/17/06
to ccppbrasil
O return é opcional para a funcao main. No caso do VC++ 6 não segue o
padrão neste caso e é obrigatório colocar.
Não colei o"#include <cmath>" aqui no fórum, está faltando.

Estou usando o VC++ 2005 express. A função pow que é utilizada é
esta:

template<class _Ty> inline
_Ty _Pow_int(_Ty _X, int _Y)
{unsigned int _N;
if (_Y >= 0)
_N = (unsigned int)_Y;
else
_N = (unsigned int)(-_Y);
for (_Ty _Z = _Ty(1); ; _X *= _X)
{if ((_N & 1) != 0)
_Z *= _X;
if ((_N >>= 1) == 0)
return (_Y < 0 ? _Ty(1) / _Z : _Z); }}

inline double __CRTDECL pow(__in double _X, __in int _Y)
{return (_Pow_int(_X, _Y)); }


A função _getwch() é para unicode, troque para getch() que não vai
fazer nenhuma diferença neste exemplo.

Mas conseguiu rodar?

No VC++ 6 deve dar erros ou warning nos templates. Nao tenho mais o
VC++ 6.0 pra testar.

Thiago Adams

unread,
May 17, 2006, 1:41:20 PM5/17/06
to ccppbrasil
cin.clear não faz o que eu espero.
Para quem compilou o programa pode dar uma olhadinha na funcao get
value.
Minha intenção era em caso de error, repetir o label em vermelhor e
permitir a entrada do valor novamente. Para isso eu testo o erro no cin
e uso o comando clear.
Por estar usando estas funções do console de posicionar, limpar, eu
acredito que eu estraga o cin.
O cogido que eu gostaria que funcionasse é este:

template<class T>
void GetValue(const char * tag, T & value, int col, int &row)
{
const int w = 37;
const int r = row++;
gotoxy(col, r);
cout.width(w);
cout << InColor(White, tag);

cin >> value;
bool ok = !cin.fail();
console:Color color = ok ? Gray : Red;
gotoxy(col, r);
cout.width(w);
cout << InColor(color, tag);

if (!ok)
{
cin.clear(); //< -- aqui
row = r;
GetValue(tag, value, col, row); // tentar de novo
}
}

Leonardo Valiante

unread,
May 17, 2006, 1:46:12 PM5/17/06
to ccppb...@googlegroups.com
funcionou depois que eu "corrigi" esses detalhes...
 
Mas eu estou analisando o código e acho que há possibilidade de criar uma classe console (ou mais classes) pro código ficar OO. O que acha?
 
Porque vc criou uma struct InColor?
Não poderia ser uma classe com os dados e funções membro?
 
Esses lances de sobrecarga de operadores e template de funções são muito bons mesmo. Vou estudar mais isso....
Mas esse namespace eu ainda não tinha visto...
 

 
2006/5/17, Thiago Adams <thiago...@gmail.com>:

Thiago Adams

unread,
May 17, 2006, 2:54:54 PM5/17/06
to ccppbrasil
Como algums devem saber, eu faço uma lib de interface gráfica nas
minhas horas vagas :)

Fiz o mesmo programinha usando a lib:
Segue o código:

#include <windows.h>
#include <tflib.h>
#include <cmath>
using namespace TF;

namespace
{
struct Error : public std::exception
{
std::wstring str;
Error(const wchar_t *msg) : std::exception(""), str(msg){}

};

template<class T>
T GetValue(TextBox & txt)
{
std::wstringstream ss;
ss << txt.GetText().c_str();
T value;
ss >> value;
txt.Focus();
if (ss.fail())
throw Error(L"invalid");
return value;
}
std::wstring ToString(double d)
{
std::wstringstream ss;
ss << d;
if (ss.fail())
throw Error(L"!!");
return ss.str();
}
}

class MyWindow : public Form
{
Label label1;
Label label2;
Label label3;
TextBox txtInvest;
TextBox txtPeriodo;
TextBox txtJuros;
Button btnSolve;
TextBox txtResult;
Button btnSair;


void btnSair_Click(const TF::Object & sender)
{
Close();
}

void btnSolve_Click(const TF::Object & sender)
{
try
{
const int taxa = GetValue<int>(txtJuros);
const int periodo = GetValue<int>(txtPeriodo);
const double investimento =
GetValue<double>(txtInvest);
const double taxajuros = (double(taxa) / 100.0) / 1.0;
const double FV = investimento * std::pow(1 +
taxajuros, periodo);
txtResult.SetText(ToString(FV));
}
catch(const Error &e)
{
txtResult.SetText(e.str);
}
}

void InitializeComponent()
{
SetSize(258, 250);
SetText(L"Finanças");

label1.SetLocation(80, 20);
label1.SetSize(73, 13);
label1.SetTabIndex(0);
label1.SetText(L"Investimento: ");

label2.SetLocation(12, 71);
label2.SetSize(141, 13);
label2.SetTabIndex(1);
label2.SetText(L"Juros no periodo (0 - 100%) :");

label3.SetLocation(45, 45);
label3.SetSize(108, 13);
label3.SetTabIndex(2);
label3.SetText(L"Período de interesse:");

txtInvest.SetLocation(159, 17);
txtInvest.SetSize(84, 20);
txtInvest.SetTabIndex(3);

txtPeriodo.SetLocation(159, 42);
txtPeriodo.SetSize(84, 20);
txtPeriodo.SetTabIndex(4);

txtJuros.SetLocation(159, 68);
txtJuros.SetSize(84, 20);
txtJuros.SetTabIndex(5);

btnSolve.SetLocation(15, 110);
btnSolve.SetSize(105, 31);
btnSolve.SetTabIndex(6);
btnSolve.SetText(L"Calcular");
btnSolve.Click = EventHandler(this,
&MyWindow::btnSolve_Click);

txtResult.SetLocation(159, 116);
txtResult.SetSize(83, 20);
txtResult.SetTabIndex(7);

btnSair.SetLocation(83, 182);
btnSair.SetSize(83, 29);
btnSair.SetTabIndex(8);
btnSair.SetText(L"Sair");
btnSair.Click = EventHandler(this,
&MyWindow::btnSair_Click);

AddChild(btnSair);
AddChild(txtResult);
AddChild(btnSolve);
AddChild(txtJuros);
AddChild(txtPeriodo);
AddChild(txtInvest);
AddChild(label3);
AddChild(label2);
AddChild(label1);
}

public:
MyWindow()
{
InitializeComponent();
}
};


int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MyWindow wnd;
Application().Run(wnd);
return 0;
}

Coloquei o código e um screenshot na minha página:
http://paginas.terra.com.br/informatica/thiago_adams/tf18_port.htm

Qualquer semelhança com o .net não é mera coincidencia. :) Estou
usando os mesmos nomes de função (quando existem), para pode usar o
editor do c#. Não fiz IDE ainda.
Mas as semelhanças acabam por ai. O consumo de memoria e o desenpenho
não é semelhante. :)

Thiago Adams

unread,
May 17, 2006, 3:21:14 PM5/17/06
to ccppbrasil
>Mas eu estou analisando o código e acho que há possibilidade de criar uma
>classe console (ou mais classes) pro código ficar OO. O que acha?
Eu já fiz isso um tempo atrás, mas agora acho que foi uma má ideia..
misturei muito as coisas formatacao e console e acho que não vale a
pena ter um "estado" para o console.
http://paginas.terra.com.br/informatica/thiago_adams/console_port.htm
---
inColor
Criei para usar o destructor e deselecionar a cor.
---

OO é muito bom. Eu sempre defendo juntamente com C++. Mas é ótimo na
minha opnião e que C++ seja multiparadigma, diferente do c# ou java.

wishmaster_rs

unread,
May 17, 2006, 8:52:36 PM5/17/06
to ccppbrasil
He he he he, olha:
Eu não tenho problemas em instalar programas... de qualquer tipo... se
não, eu nem começava a aprender C++, fala sério. É que eu estou
usando o Dev C++, é um compilador gratuito (open). Eu estou com Visual
Studio 2005 aqui, mas tô sem CD virgem para gravá-lo e levar pro meu
micro. Não tem lugar aqui perto que vende CD, é f**@! Eu também tô
com o Windows SDK. Essa semana eu vou instalar o Visual Studio e vou
compilar o teu código, tenho muita curiosidade de ver o teu programa
funcionando.

Sobre namespaces, não sei se tem sobre isso no livro. Eu dei uma
olhada por cima no índice eu não vi nada sobre. Deve ser pelo fato
que você mencionou aí em cima, do tratamento de exceções. Me
explica melhor:

Se eu quiser usar tudo que tem na biblioteca cmath, eu tenho que
escrever isso:

#include <cmatch>
using <<<<<<<<<<<<<<<<<< E O RESTO??? Isso que eu não entendi...

Por favor, tenha paciência, ok?? Ah, por falar em paciência, no
capítulo 4 do livro, que eu começo essa semana, é somente sobre
arrays... e é bem grande o capítulo... tenho até medo....

Ah, eu gostaria de acrescentar que todos vocês estão me dando uma
grande força. Eu nem tenho palavras para agradecer!
Mas, muito obrigado a todos!

wishmaster_rs

unread,
May 21, 2006, 8:18:07 PM5/21/06
to ccppbrasil
Ah, esqueçam essa minha última pergunta, eu já aprendi. É assim:

#include <qualquercoisa>
using namespace std; <<<<<<<<< Estou usando todas as funções da lib
qualquercoisa.. É isso, né?

Wanderley Caloni Jr

unread,
May 21, 2006, 11:46:56 PM5/21/06
to ccppb...@googlegroups.com
Exato.

> X-Google-Language: PORTUGUESE,ASCII
> Received: by 10.11.53.63 with SMTP id b63mr109959cwa;
> Sun, 21 May 2006 17:18:08 -0700 (PDT)
> X-Google-Token: RYbAqgwAAABkz0KFkB65fpbXrIYRZXGy
> Received: from 201.74.76.62 by i40g2000cwc.googlegroups.com with HTTP;
> Mon, 22 May 2006 00:18:07 +0000 (UTC)
> From: "wishmaster_rs" <wishma...@gmail.com>
> To: "ccppbrasil" <ccppb...@googlegroups.com>
> Subject: ?iso-8859-1?q?Re:_float_-_Como_obter_precisão_com_esses_tipos??Date: Sun, 21 May 2006 17:18:07 -0700
> Message-ID: <1148257087....@i40g2000cwc.googlegroups.com>
> References: <1147642705.3...@i40g2000cwc.googlegroups.com>
> <1147723399.5...@u72g2000cwu.googlegroups.com>
> <1147724443.4...@u72g2000cwu.googlegroups.com>
> <1147726633.0...@j55g2000cwa.googlegroups.com>
> <1147738409.6...@i39g2000cwa.googlegroups.com>
> <1147812679.1...@j55g2000cwa.googlegroups.com>
> <1147816055....@38g2000cwa.googlegroups.com>
> <1147820352.7...@j73g2000cwa.googlegroups.com>
> <1147832372.0...@y43g2000cwc.googlegroups.com>
> <1147855712.2...@j33g2000cwa.googlegroups.com>
> <a684d0100605170503l1b5...@mail.gmail.com>
> <1147913556....@38g2000cwa.googlegroups.com>
> User-Agent: G2/0.2
> X-HTTP-UserAgent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1),gzip(gfe),gzip(gfe)
> Mime-Version: 1.0
> Content-Type: text/plain; charsetISO-8859-1
> Content-Transfer-Encoding: quoted-printable

wishmaster_rs

unread,
May 22, 2006, 12:27:16 AM5/22/06
to ccppbrasil
Valeu Wanderley, assim fica muito mais fácil.
Em vez de escrever dez (ou mais) linhas using std::várias_funções,
eu escrevo apenas:

#include <cmath>
#include <iostream>
#include <iomanip>
#include <ctime>
using namespace std; // <-- Pronto, aqui está tudo !!!

Assim ficou muito mais fácil programar (pelo menos por enquanto).

Ah, acho que não devemos mais chamar os "programinhas"
(he he he he) de "programinhas" e sim de "compilação expressa" ou PRR
(Programinha de Resposta Rápida).

Vai que alguma ONG à favor dos "programinhas" se sente insultada, né?
Aí, a gente tá F¨$#*+!*&%...

Ops... eu falei programinha... foi mal ;-D

"É a jornada o que interessa, não o destino!"

Thiago Adams

unread,
May 22, 2006, 2:17:04 PM5/22/06
to ccppbrasil
Uma dica sobre namespaces...

Não coloque using xxxx; em arquivos de header.

Isso é uma politica para evitar que os includes insiram namespaces sem
que você possa escolher se quer ou não quer.

Thiago Adams

unread,
May 22, 2006, 2:38:16 PM5/22/06
to ccppbrasil
Mais um exemplo deste programa com interface.
Windows usando WTL.

//#includes aqui...

using namespace std;

CAppModule _Module;

namespace
{
struct Error
{
std::wstring str;
Error(const wchar_t *msg) : str(msg){}
};

template<class T>
T GetValue(HWND txt)
{
TCHAR buf[50];
::GetWindowText(txt, buf, 50);

std::wstringstream ss;
ss << buf;
T value;
ss >> value;
::SetFocus(txt);


if (ss.fail())
throw Error(L"invalid");
return value;
}
std::wstring ToString(double d)
{
std::wstringstream ss;
ss << d;
if (ss.fail())
throw Error(L"!!");
return ss.str();
}
}


class CMainDlg : public CDialogImpl<CMainDlg>
{
public:
enum { IDD = IDD_MAINDLG };

BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
COMMAND_HANDLER(IDC_BUTTON1, BN_CLICKED, OnBnClickedButton1)
END_MSG_MAP()

LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM
/*lParam*/, BOOL& /*bHandled*/)
{
CenterWindow();

HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(),
MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXICON),
::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
SetIcon(hIcon, TRUE);
HICON hIconSmall =
(HICON)::LoadImage(_Module.GetResourceInstance(),
MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON),
::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
SetIcon(hIconSmall, FALSE);

return TRUE;
}


LRESULT OnCancel(WORD /*wNotifyCode*/,
WORD wID,
HWND /*hWndCtl*/,
BOOL& /*bHandled*/)
{
EndDialog(wID);
return 0;
}

LRESULT OnBnClickedButton1(WORD /*wNotifyCode*/,
WORD /*wID*/,
HWND /*hWndCtl*/,
BOOL& /*bHandled*/)
{
try
{
const int taxa = GetValue<int>(GetDlgItem(IDC_JUROS));
const int periodo = GetValue<int>(GetDlgItem(IDC_PERIODO));

const double investimento =
GetValue<double>(GetDlgItem(IDC_INVEST));
const double taxajuros = (double(taxa) / 100.0) / 1.0;
const double FV = investimento * std::pow(1 +
taxajuros, periodo);
::SetWindowTextW(GetDlgItem(IDC_RESULT),
ToString(FV).c_str());
}
catch(const Error &e)
{
::SetWindowTextW(GetDlgItem(IDC_RESULT), e.str.c_str());
}
return 0;
}
};


int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/,
LPTSTR lpstrCmdLine,
int nCmdShow)
{
HRESULT hRes = ::CoInitialize(NULL);

::DefWindowProc(NULL, 0, 0, 0L);

AtlInitCommonControls(ICC_BAR_CLASSES);

hRes = _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes));

int nRet = 0;
{
CMainDlg dlgMain;
nRet = dlgMain.DoModal();
}

_Module.Term();
::CoUninitialize();

return nRet;
}

--------
Obs: Tem ainda o arquivo .rc que contém a definição do dialog e
aquivos com os IDs dos controles.

Reply all
Reply to author
Forward
0 new messages