Can a floating-point value truly be "truncated"? - judge for yourself:
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream>
#include <iomanip>
usingnamespace std;
int main()
{
double x = 1234.5678;
x = (int)( 100 * x ) / 100.0;
cout.setf( ios::fixed );
for ( int i = 2; i <= 16; i++ ) cout << setprecision( i ) << x << endl;
}
> If a float holds 1234.5678, truncation to 2 decimal digits would be 1234.56.
I think that what lastchance was trying to point out is that there may not be a floating point representation for the precise mathematical value 1234.56
Very good. Now, for extra credit, change (in the post two above this) your line << setprecision(7) /// else will round
to << fixed << setprecision(16) /// else will round
and observe what happens (once you've included all the headers).
#include <iostream>
#include <cmath>
#include <limits>
#include <iomanip>
int main()
{
constdouble value = 1234.56 ;
constexprauto N = std::numeric_limits<double>::digits10 + 1 ;
std::cout << std::boolalpha << "iec559? " << std::numeric_limits<double>::is_iec559 << '\n'
<< std::fixed << std::setprecision(N)
<< "representable numbers around 1234.56\nto about "
<< N << " digits after the decimal point\n" ;
constdouble a_lower_value = std::nexttoward( std::nexttoward( value, value-1 ), value-1 ) ;
constdouble a_higher_value = std::nexttoward( std::nexttoward( value, value+1 ), value+1 ) ;
for( double v = a_lower_value ; v <= a_higher_value ; v = std::nexttoward( v, v+1 ) )
std::cout << v << '\n' ;
}
iec559? true
representable numbers around 1234.56
to about 16 digits after the decimal point
1234.5599999999994907
1234.5599999999997181
1234.5599999999999454
1234.5600000000001728
1234.5600000000004002
The point is that a floating-point number like 1234.56 cannot be stored precisely. Consequently, "truncation" is meaningless.
As @JLBorges points out, there are actually several distinct numbers which would be printed out as 1234.56 to a moderate precision. Which particular one of those numbers would you like any trunc() function to return?
Try this program - absolutely no truncation needed. x is already assigned the value that you want. You can't even guarantee which side of 1234.56 the higher-precision values would fall, so writing to strings won't help you.
1 2 3 4 5 6 7 8 9 10
#include <iostream>
#include <iomanip>
usingnamespace std;
int main()
{
double x = 1234.56;
cout.setf( ios::fixed );
for ( int i = 2; i <= 16; i++ ) cout << setprecision( i ) << x << endl;
}
> The point is that a floating-point number like 1234.56 cannot be stored precisely.
> Consequently, "truncation" is meaningless.
Truncation of a floating point value is definitely not meaningless.
Most floating point values are approximations of a real number. The result of a truncation is both meaningful and useful if it is as close as possible (actually as close as needed) to the mathematical ideal of the truncated real number. This is true of the result of any floating point computation: std::sin() or 1.0/3.0 are not meaningless just because the result may not be precise representation of the actual value with infinite precision.
Absolute mathematical precision to N/finity digits is often both meaningless and misleading. It is by applying a value of precision by which measurements gain value. Whenever scientists do any math the precision is very much a part of the value of any computation. Adding precision is just sloppy.
The issue is that radix=10 and radix=2 are not digit-for-digit compatible, especially when you start playing with fractional parts. So knowing how it makes a difference at all is another level of care you must have when dealing with computers.