Click here to Skip to main content
13,087,784 members (77,137 online)
Click here to Skip to main content
Add your own
alternative version


8 bookmarked
Posted 14 Nov 2006

Printing double values with a precision, derived from the given error-bound

, 14 Nov 2006
Rate this:
Please Sign up or sign in to vote.
In this article, we will consider one way of printing double values with a precision derived from the given error-bound.


In general, C has a rather powerful way of printing different values; for example, using print patterns as 1.3lf in the example below:

double value = 1.543605908721;

printf("Value 1.3lf", value);

The only problem with this approach is that this way of defining the printing format is absolutely non-flexible.

What if one wants to print values in different formats, depending on the input of the program itself?

/*One of examples is printing an array of doubles with the given error bound.*/

In this paper, we will discuss this problem in some detail.

Originally, the article was inspired by the problem of printing probability values up to the "right digit" after the decimal point. The "right digit" is the one that corresponds to a pre-set error bound.

All examples below are adapted from Markov Reward Model Checker (MRMC) tool sources , which are written by me and are freely distributed under the GPL license.

The task

Having an array of double values, probs, and an error bound, error_bound (the same for all array elements), we would like to print those values, excluding all digits after the decimal point that are insignificant, with respect to the error bound.

For example:

double * probs = {0.565820439, 0.33339};
double error_bound = 1.0e-3;

//We would like to have the following output:

//Result: ( 0.5658, 0.3333)

Note, that the output above is made up to the 4th digit after the decimal point but not up to the 3rd as one would be expecting. The reason is that, for example, for values 0.565820439 and 0.564710439 which have a difference 1.1e-3 (greater than the given error_bound), printing them up to the 3rd digit after the decimal point would not let us recognize this difference: 0.565 and 0.564.


The main task, as surprising as it could be, is to compute up to which digit after the decimal point the values should be printed. Consider the following function that computes it:

* This method is used for getting
* the printing pattern from the error bound.
* NOTE: If we have error 1.231e-10 then the precision
* is 10+1 digits after the decimal point,
* but not 13 (as for 1.231e-10 == 1231.0e-13)!
* @param error_bound: the error bound
* @return:  the precision for the printing pattern by taking the position
*           of the first significant digit after the decimal point + 1
int get_error_bound_precision(double error_bound){
    int precision = 0;
    BOOL not_found = TRUE;
    double integer = 0, fraction = 0;
    //NOTE: If we have error 1.1e-10 then the presision

    //is 10 digits after the decimal point, but not 11.

    while ( not_found ){
        error_bound *= 10;
        fraction = modf(error_bound, &integer);
        if ( integer > 0.0 ){
            not_found = FALSE;
    //We need this +1 here to add an extra digit

    return precision + 1;

What is done here, is basically going down the digits of the error_bound and looking for the first non zero one.

The rest is fairly easy, we have to create the pattern for printing our double values, which is done by using the sprintf operator, see the function below:

* This method is used for printing the state
* probabilities vector with the given error bound.
* @param size:  the size of the probabilities vector
* @param probs:  the vector of probabilities
* @param error_bound:  the error bound
void print_state_probs(int size, double * probs, double error_bound ){
    printf("Result: ");
    //Calculate the right pattern according to the precision

    char buffer[255];
    sprintf(buffer, "%%1.%dlf", get_error_bound_precision(error_bound));
    print_pattern_vec_double(buffer, size, probs);

and then call the following simple function that would print the array of doubles using the pattern we derived earlier.

* This method is used for printing an array
* of double values according to the given pattern.
* @param pattern:  the pattern for printing each array element
* @param length: the array lenght
* @param vec: the array of doubles to be printed
void print_pattern_vec_double(const char * pattern, int length, double * vec)
    int i;
    printf("( ");
    for( i = 0 ; i < length ; i++ ){
        //NOTE: this is where the pattern for printing is used

        printf( pattern, vec[i] );
        if (i != length-1) printf(", ");
    printf(" )\n");


Here, we considered one of the simplest ways to print double values with the precision defined by some error bound.

Below, I will mention two more ways of solving the problem, which I've considered during my investigation:

  1. Having double error_bound = 1.47003454e-10 and printing values with the desired precision, taking into account the last non-zero digit of error_bound, is not feasible because actually the value stored in the double error_bound variable is not exactly 1.47003454e-10 but is something like 1.47003454000000000000329999961234769e-10, which is the desired error plus some noise.
  2. Using the IEEE floating-point standard to compute the desired precision from error_bound, does not really help. From the first glance, there is a part that gives you some knowledge about the exponential part of the number, but it is all about the power of 2, whereas we are interested in the power of 10.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Dr. Ivan S Zapreev
Instructor / Trainer Fontys Hogescholen
Netherlands Netherlands
A software architect, designer, and a researcher in formal methods, algorithms and tools. Bachelor and Masters degrees (with honors) in Theoretical Mathematics. PhD in Theoretical Computer Science. Nine (9), DBLP recognized, international research publications ( Five (5) Codeproject articles ( Fiveteen (15) years of work experience in research, design and development of Verification Algorithms, Scientific Software, Embedded Systems and Web applications. Young, energetic, pragmatic, smart, quality demanding, proactive, and eager to take responsibility. Working to the fullest, used to solving large-scale multi-disciplinary problems targeting long-run goals. Looking for a new challenge in a field of research and technical leadership.

Experience with development processes: Waterfall model; V-model (Rational Unified Process); Agile (SCRUM)

* Doing formal and applied research in the field of System and Software Verification
* Acquiring information, sharing knowledge, lecturing, mentoring, motivating and evaluating people.
* Creating object oriented architectures and developing large scale projects.

Experience with tools:
ASD suite, Rational Rose, Borland Together, Eclipse, Rational Soda for Word, Idea, JBuilder4/5/6/7, jdk1.3-1.6, Ant 1.x.x, Make, WebSphere, Tomcat 3.x, Weblogic, MySQL, Matlab 6.5 SP13, Clear Case, Clear Quest, Microsoft Visio.

Experience with programming languages:
Java (5 years), C (5 years), C++ (4 years), UML (4 years), CSS (2 years), HTML (2 years), Modula2 (2 years), Oberon (2 years), Microsoft .NET C# (1.5 year, ASP), SQL (1 year), OQL (1 year), XML (1 years), CSH (1 years), EL-76 (1 year), Visual Basic .NET (0.5 years), Pick Basic (0.5 years), OCL (0.5 years), JSP (1 year), Scala (0.3 years)

Knowledge and use of Version Control Systems:
SVN, CVS, GIT, Clearcase, SCCS

You may also be interested in...

Comments and Discussions

-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170813.1 | Last Updated 14 Nov 2006
Article Copyright 2006 by Dr. Ivan S Zapreev
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid