By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
428,591 Members | 629 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 428,591 IT Pros & Developers. It's quick & easy.

Correct precision with printf

P: n/a
I read the thread Floating point rounding error and
I saw Richard Heathfield's description with several
lines like:
0.1 = 1/2 = 0.5 - too large
0.01 = 1/4 = 0.25 - too large
0.001 = 1/8 = 0.125 - too large
....

And I wanted to write such a program that output
lines like that. My attempt is below, and I don't
know how I should print the third column, with
printf I either get too low precision or a lot of
zeros after the first lines. Right now I just
have %.20f in the format string, but I wonder
how I can do it like Heathfield did and remove
trailing zeroes. Otherwise I wonder if my program
is a correct C program. Thanks!

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>

/* Examines the binary representation in the array to
see if it is smaller or larger than value.
Prints a new line containing the info and returns
the result of the comparison. */
int examine(char *data, size_t length, double value)
{
size_t i;
int num, den;
double result;

/* Shorten the length */
i = length;
while (i-- && data[i] == 0) {
length--;
}
assert(length != 0);

num = 0;
den = 1;
printf("0.");
for (i = 0; i < length; i++) {
den *= 2;
num *= 2;
if (data[i] != 0) {
putchar('1');
num++;
}
else
putchar('0');
}

result = (double)num/den;
printf(" = %d/%d = %.20f", num, den, result);
if (result == value) {
printf(" - same\n");
return 0;
}
else if (result value) {
printf(" - too large\n");
return 1;
}
else {
printf(" - too small\n");
return -1;
}
}

int main(int argc, char *argv[])
{
char array[17] = { 0 };
double val;
int i;
int cmp;

if (argc < 2)
return EXIT_FAILURE;

val = strtod(argv[1], NULL);
if (errno != 0)
return EXIT_FAILURE;

array[0] = 1;
for (i = 1; i < 17; i++) {
cmp = examine(array, i, val);
if (cmp == 0)
return 0;
else if (cmp < 1) {
array[i] = 1;
}
else {
array[i - 1] = 0;
array[i] = 1;
}
}
return EXIT_SUCCESS;
}

Jun 17 '07 #1
Share this Question
Share on Google+
4 Replies


P: n/a
ba******@hushmail.com said:
I read the thread Floating point rounding error and
I saw Richard Heathfield's description with several
lines like:
0.1 = 1/2 = 0.5 - too large
0.01 = 1/4 = 0.25 - too large
0.001 = 1/8 = 0.125 - too large
...

And I wanted to write such a program that output
lines like that. My attempt is below,
Applause!

For extra credit, make it work to an arbitrary precision.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 17 '07 #2

P: n/a

<ba******@hushmail.comha scritto nel messaggio
news:11*********************@n60g2000hse.googlegro ups.com...
>I read the thread Floating point rounding error and
I saw Richard Heathfield's description with several
lines like:
0.1 = 1/2 = 0.5 - too large
0.01 = 1/4 = 0.25 - too large
0.001 = 1/8 = 0.125 - too large
...

And I wanted to write such a program that output
lines like that. My attempt is below, and I don't
know how I should print the third column, with
printf I either get too low precision or a lot of
zeros after the first lines. Right now I just
have %.20f in the format string, but I wonder
how I can do it like Heathfield did and remove
trailing zeroes. Otherwise I wonder if my program
is a correct C program. Thanks!
Use the %g conversion instead of %f.
BTW, have you tried it with an argument <= 0 or >= 1?
(And before returning EXIT_FAILURE I'd give the user a clue of why
the program failed.)
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>

/* Examines the binary representation in the array to
see if it is smaller or larger than value.
Prints a new line containing the info and returns
the result of the comparison. */
int examine(char *data, size_t length, double value)
{
size_t i;
int num, den;
double result;

/* Shorten the length */
i = length;
while (i-- && data[i] == 0) {
length--;
}
assert(length != 0);

num = 0;
den = 1;
printf("0.");
for (i = 0; i < length; i++) {
den *= 2;
num *= 2;
if (data[i] != 0) {
putchar('1');
num++;
}
else
putchar('0');
}

result = (double)num/den;
printf(" = %d/%d = %.20f", num, den, result);
if (result == value) {
printf(" - same\n");
return 0;
}
else if (result value) {
printf(" - too large\n");
return 1;
}
else {
printf(" - too small\n");
return -1;
}
}

int main(int argc, char *argv[])
{
char array[17] = { 0 };
double val;
int i;
int cmp;

if (argc < 2)
return EXIT_FAILURE;

val = strtod(argv[1], NULL);
if (errno != 0)
return EXIT_FAILURE;

array[0] = 1;
for (i = 1; i < 17; i++) {
cmp = examine(array, i, val);
if (cmp == 0)
return 0;
else if (cmp < 1) {
array[i] = 1;
}
else {
array[i - 1] = 0;
array[i] = 1;
}
}
return EXIT_SUCCESS;
}

Jun 17 '07 #3

P: n/a
On Jun 17, 10:20 pm, "Army1987" <please....@for.itwrote:
<banan...@hushmail.comha scritto nel messaggionews:11*********************@n60g2000hse. googlegroups.com...
I read the thread Floating point rounding error and
I saw Richard Heathfield's description with several
lines like:
0.1 = 1/2 = 0.5 - too large
0.01 = 1/4 = 0.25 - too large
0.001 = 1/8 = 0.125 - too large
...
And I wanted to write such a program that output
lines like that. My attempt is below, and I don't
know how I should print the third column, with
printf I either get too low precision or a lot of
zeros after the first lines. Right now I just
have %.20f in the format string, but I wonder
how I can do it like Heathfield did and remove
trailing zeroes. Otherwise I wonder if my program
is a correct C program. Thanks!

Use the %g conversion instead of %f.
Thanks! I missed that when I read about the specifiers,
didn't know it was that easy.
BTW, have you tried it with an argument <= 0 or >= 1?
(And before returning EXIT_FAILURE I'd give the user a clue of why
the program failed.)
Yeah, I knew of those two points, I should have said that.
But thanks for pointing that out.

Jun 18 '07 #4

P: n/a
ba******@hushmail.com writes:
I read the thread Floating point rounding error and
I saw Richard Heathfield's description with several
lines like:
0.1 = 1/2 = 0.5 - too large
0.01 = 1/4 = 0.25 - too large
0.001 = 1/8 = 0.125 - too large
...

And I wanted to write such a program that output
lines like that. My attempt is below, and I don't
know how I should print the third column, with
printf I either get too low precision or a lot of
zeros after the first lines. Right now I just
have %.20f in the format string, but I wonder
how I can do it like Heathfield did and remove
trailing zeroes.
%g has already been suggested, but %.*g (or %.*f) has not. This lets
you pass the desired precision as a parameter to *printf function.
The variable 'length' is a good first stab at the right value.

--
Ben.
Jun 18 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.