Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Is this the correct way to do this template?

Reply
Thread Tools

Is this the correct way to do this template?

 
 
Jim Langston
Guest
Posts: n/a
 
      06-03-2006
I have a template I call StrmConvert, which uses std::stringstream to
convert from any type to any other type that can be used by stringstring.
This is what it looks like:

template<typename T, typename F > T StrmConvert( F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}

it works well for me, but I find it can be a lot of typing. I have it in a
namespace called jml so I wind up doing things like this:

std::cout << jml::StrmConvert<std::string>( floatvalue );

I find that 99% of the time I'm converting to std::string so I've decided to
specialize it (if that is the right term) this way:

template<typename F> std::string StrmConvert( F from )
{
return StrmConvert<std::string>( from );
}

and it seems to work. Now I can say:

std::cout << jml::StrmConvert( floatvalue );

because if I don't specify the typename T is uses the std::string. Is this
the right way to do it? It seems to work, but I want to know if there can
be any problems with this. I did this test and it works, I'm just a n00b
when it comes to templates.

#include <string>
#include <iostream>
#include <sstream>

template<typename T, typename F > T StrmConvert( F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}

template<typename F> std::string StrmConvert( F from )
{
return StrmConvert<std::string>( from );
}

int main ()
{

std::cout << StrmConvert<std::string>( 123.45 ) << std::endl;
std::cout << StrmConvert( 123.45 ) << std::endl;

float MyValue = StrmConvert<float>( "123.456" );
std::cout << MyValue << std::endl;

std::string wait;
std::cin >> wait;
}



 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      06-03-2006
Jim Langston wrote:

> I have a template I call StrmConvert, which uses std::stringstream to
> convert from any type to any other type that can be used by stringstring.
> This is what it looks like:
>
> template<typename T, typename F > T StrmConvert( F from )
> {
> std::stringstream temp;
> temp << from;
> T to = T();
> temp >> to;
> return to;
> }
>
> it works well for me, but I find it can be a lot of typing. I have it in
> a namespace called jml so I wind up doing things like this:
>
> std::cout << jml::StrmConvert<std::string>( floatvalue );
>
> I find that 99% of the time I'm converting to std::string so I've decided
> to specialize it (if that is the right term) this way:
>
> template<typename F> std::string StrmConvert( F from )
> {
> return StrmConvert<std::string>( from );
> }
>
> and it seems to work. Now I can say:
>
> std::cout << jml::StrmConvert( floatvalue );
>
> because if I don't specify the typename T is uses the std::string. Is
> this
> the right way to do it? It seems to work, but I want to know if there can
> be any problems with this. I did this test and it works, I'm just a n00b
> when it comes to templates.
>
> #include <string>
> #include <iostream>
> #include <sstream>
>
> template<typename T, typename F > T StrmConvert( F from )
> {
> std::stringstream temp;
> temp << from;
> T to = T();


T to;

> temp >> to;
> return to;
> }


Also, you may want to throw something if the conversion fails. Anyhow,
boost::lexical_cast is maybe what you try to reinvent here.

>
> template<typename F> std::string StrmConvert( F from )
> {
> return StrmConvert<std::string>( from );
> }
>
> int main ()
> {
>
> std::cout << StrmConvert<std::string>( 123.45 ) << std::endl;


I fail to see what that buys you compared to

std::cout << 123.45 << std::endl;

Also note that the StrmConvert<> is broken with regard to float types:
conversion will not even remotely make a round-trip:

double x;
double y = StrmConvert<double>( x );

This will turn y into a 6-digit precission approximation (I think << has a
default precision like that). Usually that is not what you want.

Also note that operator<< and operator>> are not strict inverses for some
other types (e.g., std::string). Your cast may lead to surprising results.

> std::cout << StrmConvert( 123.45 ) << std::endl;
>
> float MyValue = StrmConvert<float>( "123.456" );
> std::cout << MyValue << std::endl;
>
> std::string wait;
> std::cin >> wait;
> }



Best

Kai-Uwe Bux
 
Reply With Quote
 
 
 
 
Jim Langston
Guest
Posts: n/a
 
      06-03-2006
"Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Jim Langston wrote:
>
>> I have a template I call StrmConvert, which uses std::stringstream to
>> convert from any type to any other type that can be used by stringstring.
>> This is what it looks like:
>>
>> template<typename T, typename F > T StrmConvert( F from )
>> {
>> std::stringstream temp;
>> temp << from;
>> T to = T();
>> temp >> to;
>> return to;
>> }
>>
>> it works well for me, but I find it can be a lot of typing. I have it in
>> a namespace called jml so I wind up doing things like this:
>>
>> std::cout << jml::StrmConvert<std::string>( floatvalue );
>>
>> I find that 99% of the time I'm converting to std::string so I've decided
>> to specialize it (if that is the right term) this way:
>>
>> template<typename F> std::string StrmConvert( F from )
>> {
>> return StrmConvert<std::string>( from );
>> }
>>
>> and it seems to work. Now I can say:
>>
>> std::cout << jml::StrmConvert( floatvalue );
>>
>> because if I don't specify the typename T is uses the std::string. Is
>> this
>> the right way to do it? It seems to work, but I want to know if there
>> can
>> be any problems with this. I did this test and it works, I'm just a n00b
>> when it comes to templates.
>>
>> #include <string>
>> #include <iostream>
>> #include <sstream>
>>
>> template<typename T, typename F > T StrmConvert( F from )
>> {
>> std::stringstream temp;
>> temp << from;
>> T to = T();

>
> T to;
>
>> temp >> to;
>> return to;
>> }

>
> Also, you may want to throw something if the conversion fails.


I've thought about throwing, but then I would need to catch every time I use
StrmConvert, which is a lot. I would rather take the default value which is
what the T(); should be giving me. If there is a case where I want to know
if it's a bad value, I'll test for it outside the template before I call it
or after.

> Anyhow,
> boost::lexical_cast is maybe what you try to reinvent here.


Most likely. I just don't use, but once it becomes part of the standard I
will.

>> template<typename F> std::string StrmConvert( F from )
>> {
>> return StrmConvert<std::string>( from );
>> }
>>
>> int main ()
>> {
>>
>> std::cout << StrmConvert<std::string>( 123.45 ) << std::endl;

>
> I fail to see what that buys you compared to
>
> std::cout << 123.45 << std::endl;


Well, usually this would be used for outputing text using a graphical call.
Something like:
draw_text( x, y, "The value is: " + jml::StrmConvert( HPs ) );

The std::cout here was just done for my test since it gained me nothing to
bring in all my graphical code for a test.

> Also note that the StrmConvert<> is broken with regard to float types:
> conversion will not even remotely make a round-trip:
>
> double x;
> double y = StrmConvert<double>( x );
>
> This will turn y into a 6-digit precission approximation (I think << has a
> default precision like that). Usually that is not what you want.


Luckily for me, this is usually what I want. As I said, this is normally
used for simple output. Incidently, if I do need precision, is there anyway
I can fix it?

> Also note that operator<< and operator>> are not strict inverses for some
> other types (e.g., std::string). Your cast may lead to surprising results.


Please explain? I don't understand what you're saying here.

>> std::cout << StrmConvert( 123.45 ) << std::endl;
>>
>> float MyValue = StrmConvert<float>( "123.456" );
>> std::cout << MyValue << std::endl;
>>
>> std::string wait;
>> std::cin >> wait;
>> }


Thanks for the code revue.


 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      06-03-2006
Jim Langston wrote:

> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> Jim Langston wrote:
>>
>>> I have a template I call StrmConvert, which uses std::stringstream to
>>> convert from any type to any other type that can be used by
>>> stringstring. This is what it looks like:
>>>
>>> template<typename T, typename F > T StrmConvert( F from )
>>> {
>>> std::stringstream temp;
>>> temp << from;
>>> T to = T();
>>> temp >> to;
>>> return to;
>>> }

[snip]
>>> int main ()
>>> {
>>>
>>> std::cout << StrmConvert<std::string>( 123.45 ) << std::endl;

>>
>> I fail to see what that buys you compared to
>>
>> std::cout << 123.45 << std::endl;

>
> Well, usually this would be used for outputing text using a graphical
> call. Something like:
> draw_text( x, y, "The value is: " + jml::StrmConvert( HPs ) );
>
> The std::cout here was just done for my test since it gained me nothing to
> bring in all my graphical code for a test.
>
>> Also note that the StrmConvert<> is broken with regard to float types:
>> conversion will not even remotely make a round-trip:
>>
>> double x;
>> double y = StrmConvert<double>( x );
>>
>> This will turn y into a 6-digit precission approximation (I think << has
>> a default precision like that). Usually that is not what you want.

>
> Luckily for me, this is usually what I want. As I said, this is normally
> used for simple output. Incidently, if I do need precision, is there
> anyway I can fix it?


Yes, you would need to set the precision of the stringstream to the right
value. You could either have the template do that based upon the floating
type (partial specialization) or you pass a precision parameter as a second
argument and have it default to something reasonable.

>
>> Also note that operator<< and operator>> are not strict inverses for some
>> other types (e.g., std::string). Your cast may lead to surprising
>> results.

>
> Please explain? I don't understand what you're saying here.


Well, I mistook your template for a cast. So I was concerned with code like:

std::string s = "hello world!";
std::string t = my_fancy_cast< std::string >( s );

Now, given the naive stringstream implementation, the string t will
be "hello" and not "hello world!".



Now that I know you just want to convert to std::string so that you can
output anything via some API that takes strings or C-Strings, what about:

template< typename T >
std::string any_to_string ( T const & obj ) {
std::stringstream dummy;
if ( !( dummy << obj ) ) {
throw( std::runtime_error( "conversion to string failed" ) );
}
return dummy.str();
}

or:

template< typename T >
std::string any_to_string ( T const & obj, unsigned short prec = 6 ) {
std::stringstream dummy;
if ( !( dummy << std::setprecision(prec) << obj ) ) {
throw( std::runtime_error( "conversion to string failed" ) );
}
return dummy.str();
}


Best

Kai-Uwe Bux
 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      06-03-2006

"Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Jim Langston wrote:
>
>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed)...
>>> Jim Langston wrote:
>>>
>>>> I have a template I call StrmConvert, which uses std::stringstream to
>>>> convert from any type to any other type that can be used by
>>>> stringstring. This is what it looks like:
>>>>
>>>> template<typename T, typename F > T StrmConvert( F from )
>>>> {
>>>> std::stringstream temp;
>>>> temp << from;
>>>> T to = T();
>>>> temp >> to;
>>>> return to;
>>>> }

> [snip]
>>>> int main ()
>>>> {
>>>>
>>>> std::cout << StrmConvert<std::string>( 123.45 ) << std::endl;
>>>
>>> I fail to see what that buys you compared to
>>>
>>> std::cout << 123.45 << std::endl;

>>
>> Well, usually this would be used for outputing text using a graphical
>> call. Something like:
>> draw_text( x, y, "The value is: " + jml::StrmConvert( HPs ) );
>>
>> The std::cout here was just done for my test since it gained me nothing
>> to
>> bring in all my graphical code for a test.
>>
>>> Also note that the StrmConvert<> is broken with regard to float types:
>>> conversion will not even remotely make a round-trip:
>>>
>>> double x;
>>> double y = StrmConvert<double>( x );
>>>
>>> This will turn y into a 6-digit precission approximation (I think << has
>>> a default precision like that). Usually that is not what you want.

>>
>> Luckily for me, this is usually what I want. As I said, this is normally
>> used for simple output. Incidently, if I do need precision, is there
>> anyway I can fix it?

>
> Yes, you would need to set the precision of the stringstream to the right
> value. You could either have the template do that based upon the floating
> type (partial specialization) or you pass a precision parameter as a
> second
> argument and have it default to something reasonable.
>
>>
>>> Also note that operator<< and operator>> are not strict inverses for
>>> some
>>> other types (e.g., std::string). Your cast may lead to surprising
>>> results.

>>
>> Please explain? I don't understand what you're saying here.

>
> Well, I mistook your template for a cast. So I was concerned with code
> like:
>
> std::string s = "hello world!";
> std::string t = my_fancy_cast< std::string >( s );
>
> Now, given the naive stringstream implementation, the string t will
> be "hello" and not "hello world!".
>
>
>
> Now that I know you just want to convert to std::string so that you can
> output anything via some API that takes strings or C-Strings, what about:
>
> template< typename T >
> std::string any_to_string ( T const & obj ) {
> std::stringstream dummy;
> if ( !( dummy << obj ) ) {
> throw( std::runtime_error( "conversion to string failed" ) );
> }
> return dummy.str();
> }
>
> or:
>
> template< typename T >
> std::string any_to_string ( T const & obj, unsigned short prec = 6 ) {
> std::stringstream dummy;
> if ( !( dummy << std::setprecision(prec) << obj ) ) {
> throw( std::runtime_error( "conversion to string failed" ) );
> }
> return dummy.str();
> }


Well, sometimes I do use it to convert from strings to numbers, usually int
values.

The main use I'm using this for right now is a client/server program (game)
building and parsing strings from and to the server. Here is one real world
case of where I'm using it for this:

// Note, this is char value like "64", not a byte

CSVParser & CSVParser:perator >> (char & nOut)
{
GetField();
int tInt = jml::StrmConvert<int>( m_sField );
nOut = (char) tInt;
return *this;
}

CSVParser & CSVParser:perator >> (unsigned int & nOut)
{
GetField();
nOut = jml::StrmConvert<unsigned int>( m_sField );
return *this;
}

CSVParser & CSVParser:perator >> (unsigned long & nOut)
{
GetField();
nOut = jml::StrmConvert<unsigned long>( m_sField );
return *this;
}

CSVParser & CSVParser:perator >> (double & nOut)
{
GetField();
nOut = jml::StrmConvert<double>( m_sField );
return *this;
}

The use for double does concern me, given your comment about the precision
problems, which is why I asked how to fix it. There are some cases where
I'm transfering a float value with a number of decimal digits I need to
preserve. So far it hasn't caused any problems, but later on it will so I
will need to fix it.

Giving an optional 3rd paramter for places of precision would probably be my
best bet.


 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      06-03-2006
Jim Langston wrote:

>
> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> Jim Langston wrote:
>>
>>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>>> news:(E-Mail Removed)...
>>>> Jim Langston wrote:
>>>>
>>>>> I have a template I call StrmConvert, which uses std::stringstream to
>>>>> convert from any type to any other type that can be used by
>>>>> stringstring. This is what it looks like:
>>>>>
>>>>> template<typename T, typename F > T StrmConvert( F from )
>>>>> {
>>>>> std::stringstream temp;
>>>>> temp << from;
>>>>> T to = T();
>>>>> temp >> to;
>>>>> return to;
>>>>> }

[snip]
>
> The use for double does concern me, given your comment about the precision
> problems, which is why I asked how to fix it. There are some cases where
> I'm transfering a float value with a number of decimal digits I need to
> preserve. So far it hasn't caused any problems, but later on it will so I
> will need to fix it.
>
> Giving an optional 3rd paramter for places of precision would probably be
> my best bet.


Ok, here is a hack that I use to determine how many digits I need to print
in order to preserve the accuracy.


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

template < typename T >
unsigned short max_prec ( void ) {
return
2 +
static_cast< unsigned short >
( - std::log( std::numeric_limits<T>::epsilon() ) / std::log( 10.0 ) );
}

int main ( void ) {
std::cout << "float: " << max_prec< float >() << '\n'
<< "double: " << max_prec< double >() << '\n'
<< "long double: " << max_prec< long double >() << '\n';
}


If you use max_prec() digits, you should be fine -- if it wasn't for the
usual pitfalls of floats, that is.



Best

Kai-Uwe Bux
 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      06-03-2006

"Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Jim Langston wrote:
>
>>
>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed)...
>>> Jim Langston wrote:
>>>
>>>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>>>> news:(E-Mail Removed)...
>>>>> Jim Langston wrote:
>>>>>
>>>>>> I have a template I call StrmConvert, which uses std::stringstream to
>>>>>> convert from any type to any other type that can be used by
>>>>>> stringstring. This is what it looks like:
>>>>>>
>>>>>> template<typename T, typename F > T StrmConvert( F from )
>>>>>> {
>>>>>> std::stringstream temp;
>>>>>> temp << from;
>>>>>> T to = T();
>>>>>> temp >> to;
>>>>>> return to;
>>>>>> }

> [snip]
>>
>> The use for double does concern me, given your comment about the
>> precision
>> problems, which is why I asked how to fix it. There are some cases where
>> I'm transfering a float value with a number of decimal digits I need to
>> preserve. So far it hasn't caused any problems, but later on it will so
>> I
>> will need to fix it.
>>
>> Giving an optional 3rd paramter for places of precision would probably be
>> my best bet.

>
> Ok, here is a hack that I use to determine how many digits I need to print
> in order to preserve the accuracy.
>
>
> #include <iostream>
> #include <limits>
> #include <cmath>
>
> template < typename T >
> unsigned short max_prec ( void ) {
> return
> 2 +
> static_cast< unsigned short >
> ( - std::log( std::numeric_limits<T>::epsilon() ) / std::log( 10.0 ) );
> }
>
> int main ( void ) {
> std::cout << "float: " << max_prec< float >() << '\n'
> << "double: " << max_prec< double >() << '\n'
> << "long double: " << max_prec< long double >() << '\n';
> }
>
>
> If you use max_prec() digits, you should be fine -- if it wasn't for the
> usual pitfalls of floats, that is.


Bah, std::stringstream ignores precision on text input. That is, the follow
program outputs:
1.2345678901229999
1.23457

I guess std::stringstream can't convert from a text string to a floating
point value with any type of accuracy.

#include <iostream>
#include <string>
#include <sstream>

int main ( void )
{
std::stringstream MyStream;
MyStream.precision( 18 );

double DoubleVal = 1.234567890123;
std::string Text;

MyStream << DoubleVal;
MyStream >> Text;
std::cout << Text << std::endl;

MyStream << Text;
MyStream >> DoubleVal;
std::cout << DoubleVal << std::endl;

std::string wait;
std::cin >> wait;
}



 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      06-03-2006
Jim Langston wrote:

>
> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> Jim Langston wrote:
>>
>>>
>>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>>> news:(E-Mail Removed)...
>>>> Jim Langston wrote:
>>>>
>>>>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>>>>> news:(E-Mail Removed)...
>>>>>> Jim Langston wrote:
>>>>>>
>>>>>>> I have a template I call StrmConvert, which uses std::stringstream
>>>>>>> to convert from any type to any other type that can be used by
>>>>>>> stringstring. This is what it looks like:
>>>>>>>
>>>>>>> template<typename T, typename F > T StrmConvert( F from )
>>>>>>> {
>>>>>>> std::stringstream temp;
>>>>>>> temp << from;
>>>>>>> T to = T();
>>>>>>> temp >> to;
>>>>>>> return to;
>>>>>>> }

>> [snip]
>>>
>>> The use for double does concern me, given your comment about the
>>> precision
>>> problems, which is why I asked how to fix it. There are some cases
>>> where I'm transfering a float value with a number of decimal digits I
>>> need to
>>> preserve. So far it hasn't caused any problems, but later on it will so
>>> I
>>> will need to fix it.
>>>
>>> Giving an optional 3rd paramter for places of precision would probably
>>> be my best bet.

>>
>> Ok, here is a hack that I use to determine how many digits I need to
>> print in order to preserve the accuracy.
>>
>>
>> #include <iostream>
>> #include <limits>
>> #include <cmath>
>>
>> template < typename T >
>> unsigned short max_prec ( void ) {
>> return
>> 2 +
>> static_cast< unsigned short >
>> ( - std::log( std::numeric_limits<T>::epsilon() ) / std::log( 10.0 )
>> );
>> }
>>
>> int main ( void ) {
>> std::cout << "float: " << max_prec< float >() << '\n'
>> << "double: " << max_prec< double >() << '\n'
>> << "long double: " << max_prec< long double >() << '\n';
>> }
>>
>>
>> If you use max_prec() digits, you should be fine -- if it wasn't for the
>> usual pitfalls of floats, that is.

>
> Bah, std::stringstream ignores precision on text input.


Huh?

> That is, the
> follow program outputs:
> 1.2345678901229999
> 1.23457


Ok, let's see.

> I guess std::stringstream can't convert from a text string to a floating
> point value with any type of accuracy.


It is supposed to.

> #include <iostream>
> #include <string>
> #include <sstream>
>
> int main ( void )
> {
> std::stringstream MyStream;
> MyStream.precision( 18 );
>
> double DoubleVal = 1.234567890123;
> std::string Text;
>
> MyStream << DoubleVal;
> MyStream >> Text;
> std::cout << Text << std::endl;
>
> MyStream << Text;
> MyStream >> DoubleVal;
> std::cout << DoubleVal << std::endl;


Aha! Here, you print DoubleVal to std::cout with 6 digits of precision!

> std::string wait;
> std::cin >> wait;
> }



Best

Kai-Uwe Bux
 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      06-03-2006

"Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Jim Langston wrote:
>
>>
>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed)...
>>> Jim Langston wrote:
>>>
>>>>
>>>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>>>> news:(E-Mail Removed)...
>>>>> Jim Langston wrote:
>>>>>
>>>>>> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
>>>>>> news:(E-Mail Removed)...
>>>>>>> Jim Langston wrote:
>>>>>>>
>>>>>>>> I have a template I call StrmConvert, which uses std::stringstream
>>>>>>>> to convert from any type to any other type that can be used by
>>>>>>>> stringstring. This is what it looks like:
>>>>>>>>
>>>>>>>> template<typename T, typename F > T StrmConvert( F from )
>>>>>>>> {
>>>>>>>> std::stringstream temp;
>>>>>>>> temp << from;
>>>>>>>> T to = T();
>>>>>>>> temp >> to;
>>>>>>>> return to;
>>>>>>>> }
>>> [snip]
>>>>
>>>> The use for double does concern me, given your comment about the
>>>> precision
>>>> problems, which is why I asked how to fix it. There are some cases
>>>> where I'm transfering a float value with a number of decimal digits I
>>>> need to
>>>> preserve. So far it hasn't caused any problems, but later on it will
>>>> so
>>>> I
>>>> will need to fix it.
>>>>
>>>> Giving an optional 3rd paramter for places of precision would probably
>>>> be my best bet.
>>>
>>> Ok, here is a hack that I use to determine how many digits I need to
>>> print in order to preserve the accuracy.
>>>
>>>
>>> #include <iostream>
>>> #include <limits>
>>> #include <cmath>
>>>
>>> template < typename T >
>>> unsigned short max_prec ( void ) {
>>> return
>>> 2 +
>>> static_cast< unsigned short >
>>> ( - std::log( std::numeric_limits<T>::epsilon() ) / std::log( 10.0 )
>>> );
>>> }
>>>
>>> int main ( void ) {
>>> std::cout << "float: " << max_prec< float >() << '\n'
>>> << "double: " << max_prec< double >() << '\n'
>>> << "long double: " << max_prec< long double >() << '\n';
>>> }
>>>
>>>
>>> If you use max_prec() digits, you should be fine -- if it wasn't for the
>>> usual pitfalls of floats, that is.

>>
>> Bah, std::stringstream ignores precision on text input.

>
> Huh?
>
>> That is, the
>> follow program outputs:
>> 1.2345678901229999
>> 1.23457

>
> Ok, let's see.
>
>> I guess std::stringstream can't convert from a text string to a floating
>> point value with any type of accuracy.

>
> It is supposed to.
>
>> #include <iostream>
>> #include <string>
>> #include <sstream>
>>
>> int main ( void )
>> {
>> std::stringstream MyStream;
>> MyStream.precision( 18 );
>>
>> double DoubleVal = 1.234567890123;
>> std::string Text;
>>
>> MyStream << DoubleVal;
>> MyStream >> Text;
>> std::cout << Text << std::endl;
>>
>> MyStream << Text;
>> MyStream >> DoubleVal;
>> std::cout << DoubleVal << std::endl;

>
> Aha! Here, you print DoubleVal to std::cout with 6 digits of precision!
>
>> std::string wait;
>> std::cin >> wait;
>> }


Well, now I really feel like a n00b. lol.

Thanks. I've settled on always setting the precision to 17 since I was
having trouble calling your template if the F wasn't a float or double, and
even inside an if block if (typeid(F) == typeid(double) ).. it wouldn't
compile because even though it would never run that code it insisted on
compiling it anyway.

template<typename T, typename F > T StrmConvert( F from )
{
std::stringstream temp;
temp.precision( 17 );
temp << from;
T to = T();
temp >> to;
return to;
}

template<typename F> std::string StrmConvert( F from )
{
return StrmConvert<std::string>( from );
}



 
Reply With Quote
 
Marcus Kwok
Guest
Posts: n/a
 
      06-05-2006
Kai-Uwe Bux <(E-Mail Removed)> wrote:
> Ok, here is a hack that I use to determine how many digits I need to print
> in order to preserve the accuracy.
>
>
> #include <iostream>
> #include <limits>
> #include <cmath>
>
> template < typename T >
> unsigned short max_prec ( void ) {
> return
> 2 +
> static_cast< unsigned short >
> ( - std::log( std::numeric_limits<T>::epsilon() ) / std::log( 10.0 ) );
> }
>
> int main ( void ) {
> std::cout << "float: " << max_prec< float >() << '\n'
> << "double: " << max_prec< double >() << '\n'
> << "long double: " << max_prec< long double >() << '\n';
> }


Is there any difference between using this and
(2 + std::numeric_limits::digits10)? Using the same definition for
max_prec() that you have,

int main ( void ) {
std::cout << "float: " << max_prec< float >() << '\n'
<< "double: " << max_prec< double >() << '\n'
<< "long double: " << max_prec< long double >() << '\n';

std::cout << "float: " << 2 + std::numeric_limits<float>::digits10 << '\n'
<< "double: " << 2 + std::numeric_limits<double>::digits10 << '\n'
<< "long double: " << 2 + std::numeric_limits<long double>::digits10 << '\n';
}

both sets display the same values. Also, I am not sure why we need to
add 2.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
simulation result is correct but synthesis result is not correct J.Ram VHDL 7 12-03-2008 01:26 PM
Uploaded File Empty but in correct folder with correct name froil Perl Misc 12 03-02-2006 01:21 PM
Correct White Balance Doesn't Mean Correct Color?? jim evans Digital Photography 28 12-27-2005 05:10 AM
correct or not correct? Dan HTML 7 10-02-2003 10:16 PM
To correct my program. please, check to find errors and correct me. joon Java 1 07-08-2003 06:13 AM



Advertisments