how to get 0.000001 with printf?

W

William Hughes

Richard said:
However, the author of the program may not be in a position to know
which of these is the right one.

As an extreme but realistic example, consider a general-purpose
calculator program. Only the user knows the appropriate precision,
and always presenting resulta to many figures would be hard to read.
A pocket calculator that didn't suppress trailing zeros would be
unpopular.

-- Richard

Yes. On the calculator in front of me if I enter 1/5 I get
..2, and if I enter 1/7 I get 0.142857142. I do not consider
this a GOOD THING. Suppressing zeros does not mean that no
default precision is being used, just that this precision is
inconsistently hidden from the user.

-William Hughes
 
R

Richard Tobin

William Hughes said:
Yes. On the calculator in front of me if I enter 1/5 I get
.2, and if I enter 1/7 I get 0.142857142. I do not consider
this a GOOD THING.

However, you are not a typical calculator user.

-- Richard
 
M

Mandar Mitra

The format requested in this thread is analogous to the "general
number" format in programs such as Microsoft Excel.

Aah, that explains it.

Here's why I asked the original question: I have been given a program
(written in a VC++ environment) that I have to clean up and
re-implement.
I was hoping to verify the correctness of my paraphrase by running a
"diff" on the various intermediate files generated by the 2 versions.
Unfortunately, the numbers in the original intermediate files are in
"microsoft" format, so diff was throwing up a lot of output.

Perhaps I should have explained this context in the original post. It
would have saved everyone a lot of trouble.

Anyway, thanks for the illuminating discussion.

Mandar.
 
K

Keith Thompson

Mandar Mitra said:
Aah, that explains it.

Here's why I asked the original question: I have been given a program
(written in a VC++ environment) that I have to clean up and
re-implement.
I was hoping to verify the correctness of my paraphrase by running a
"diff" on the various intermediate files generated by the 2 versions.
Unfortunately, the numbers in the original intermediate files are in
"microsoft" format, so diff was throwing up a lot of output.

Perhaps I should have explained this context in the original post. It
would have saved everyone a lot of trouble.

<OT>
Since you're using "diff", I presume the intermediate files are plain
text, not some funky binary format. I would run some kind of filter
over one or both of the input files, converting any floating-point
constants to a common form, and then run diff on the result. C wouldn't
be my first choice of language to implement the filter.
</OT>
 
P

pemo

Mandar Mitra said:
Aah, that explains it.

Here's why I asked the original question: I have been given a program
(written in a VC++ environment) that I have to clean up and
re-implement.
I was hoping to verify the correctness of my paraphrase by running a
"diff" on the various intermediate files generated by the 2 versions.
Unfortunately, the numbers in the original intermediate files are in
"microsoft" format, so diff was throwing up a lot of output.

Perhaps I should have explained this context in the original post. It
would have saved everyone a lot of trouble.

Anyway, thanks for the illuminating discussion.

Here's my stab at it ...

#include <stdio.h>
#include <string.h>

char * removeTralingZeros(char * buffer)
{
int i;

char * noughtPointer;

for(i = 0, noughtPointer = NULL; buffer != '\0'; ++i)
{
if(buffer == '0' && noughtPointer == NULL)
{
noughtPointer = &buffer;
}

else

if(buffer != '0')
{
noughtPointer = NULL;
}
}

if(noughtPointer != NULL)
{
*noughtPointer = '\0';
}

return buffer;
}


int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}
 
P

pemo

pemo said:
Here's my stab at it ...

BTW, I originally used a ? : in removeTralingZeros - it worked, but I got a
gcc warning:

char * removeTralingZeros(char * buffer)
{
int i;

char * noughtPointer;

for(i = 0, noughtPointer = NULL; buffer != '\0'; ++i)
{
buffer == '0' && noughtPointer == NULL ? noughtPointer =
&buffer : noughtPointer = NULL;
}

if(noughtPointer != NULL)
{
*noughtPointer = '\0';
}

return buffer;
}

[Warning] use of conditional expressions as lvalues is deprecated

I thought an lvalue was something on the left of an assignment operator?
So, there's nothing in the conditional part of this that has assignment in
it. Could someone explain the warning (compiled using -std=c99)? I've look
though the std, but can't see the problem (although, it might [probably is]
just be me - being unable to understand the prose).

char * removeTralingZeros(char * buffer)
{
int i;

char * noughtPointer;

for(i = 0, noughtPointer = NULL; buffer != '\0'; ++i)
{
buffer == '0' && noughtPointer == NULL ? noughtPointer =
&buffer : noughtPointer = NULL;
}

if(noughtPointer != NULL)
{
*noughtPointer = '\0';
}

return buffer;
}
 
W

William Hughes

pemo said:
Mandar Mitra said:
Aah, that explains it.

Here's why I asked the original question: I have been given a program
(written in a VC++ environment) that I have to clean up and
re-implement.
I was hoping to verify the correctness of my paraphrase by running a
"diff" on the various intermediate files generated by the 2 versions.
Unfortunately, the numbers in the original intermediate files are in
"microsoft" format, so diff was throwing up a lot of output.

Perhaps I should have explained this context in the original post. It
would have saved everyone a lot of trouble.

Anyway, thanks for the illuminating discussion.

Here's my stab at it ...

#include <stdio.h>
#include <string.h>

char * removeTralingZeros(char * buffer)
{
int i;

char * noughtPointer;

for(i = 0, noughtPointer = NULL; buffer != '\0'; ++i)
{
if(buffer == '0' && noughtPointer == NULL)
{
noughtPointer = &buffer;
}

else

if(buffer != '0')
{
noughtPointer = NULL;
}
}

if(noughtPointer != NULL)
{
*noughtPointer = '\0';
}

return buffer;
}


int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}


This only answers one part of the question (and that the easy part).

Assume that the floating point number x, represents
the rational 2.19994019993

Should this print out as

2.2
2.1999
2.19994
2.1999402
2.1999401999

or

2.19994019993

This question cannot be answered by merely looking at x and deciding to
strip trailing zeros. You have to decide which decimal place to
round to.
-William Hughes
 
P

pemo

William Hughes said:
Mandar Mitra said:
The format requested in this thread is analogous to the "general
number" format in programs such as Microsoft Excel.

Aah, that explains it.

Here's why I asked the original question: I have been given a program
(written in a VC++ environment) that I have to clean up and
re-implement.
I was hoping to verify the correctness of my paraphrase by running a
"diff" on the various intermediate files generated by the 2 versions.
Unfortunately, the numbers in the original intermediate files are in
"microsoft" format, so diff was throwing up a lot of output.

Perhaps I should have explained this context in the original post. It
would have saved everyone a lot of trouble.

Anyway, thanks for the illuminating discussion.

Here's my stab at it ...

#include <stdio.h>
#include <string.h>

char * removeTralingZeros(char * buffer)
{
int i;

char * noughtPointer;

for(i = 0, noughtPointer = NULL; buffer != '\0'; ++i)
{
if(buffer == '0' && noughtPointer == NULL)
{
noughtPointer = &buffer;
}

else

if(buffer != '0')
{
noughtPointer = NULL;
}
}

if(noughtPointer != NULL)
{
*noughtPointer = '\0';
}

return buffer;
}


int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}


This only answers one part of the question (and that the easy part).

Assume that the floating point number x, represents
the rational 2.19994019993

Should this print out as

2.2
2.1999
2.19994
2.1999402
2.1999401999

or

2.19994019993

This question cannot be answered by merely looking at x and deciding to
strip trailing zeros. You have to decide which decimal place to
round to.



I can't see the OP, but the extract I did see was

Mandar said:
Hello,

I'd like to print floating point numbers without trailing zeros.

So, that's what I answered.
 
W

William Hughes

pemo said:
William Hughes said:
The format requested in this thread is analogous to the "general
number" format in programs such as Microsoft Excel.

Aah, that explains it.

Here's why I asked the original question: I have been given a program
(written in a VC++ environment) that I have to clean up and
re-implement.
I was hoping to verify the correctness of my paraphrase by running a
"diff" on the various intermediate files generated by the 2 versions.
Unfortunately, the numbers in the original intermediate files are in
"microsoft" format, so diff was throwing up a lot of output.

Perhaps I should have explained this context in the original post. It
would have saved everyone a lot of trouble.

Anyway, thanks for the illuminating discussion.

Here's my stab at it ...

#include <stdio.h>
#include <string.h>

char * removeTralingZeros(char * buffer)
{
int i;

char * noughtPointer;

for(i = 0, noughtPointer = NULL; buffer != '\0'; ++i)
{
if(buffer == '0' && noughtPointer == NULL)
{
noughtPointer = &buffer;
}

else

if(buffer != '0')
{
noughtPointer = NULL;
}
}

if(noughtPointer != NULL)
{
*noughtPointer = '\0';
}

return buffer;
}


int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}


This only answers one part of the question (and that the easy part).

Assume that the floating point number x, represents
the rational 2.19994019993

Should this print out as

2.2
2.1999
2.19994
2.1999402
2.1999401999

or

2.19994019993

This question cannot be answered by merely looking at x and deciding to
strip trailing zeros. You have to decide which decimal place to
round to.



I can't see the OP, but the extract I did see was

Mandar said:
Hello,

I'd like to print floating point numbers without trailing zeros.

So, that's what I answered.


No your answer showed how to strp trailing zeros from a buffer.
The difficult part of the question is how to convert the
floating point numbers into a string in a buffer.
(Note your example starts with a string, not
a floating point number)

-William Hughes
 
P

pete

William said:
William Hughes said:
pemo wrote:
int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}

This only answers one part of the question
(and that the easy part).

Assume that the floating point number x, represents
the rational 2.19994019993

Should this print out as

2.2
2.1999
2.19994
2.1999402
2.1999401999

or

2.19994019993

This question cannot be answered
by merely looking at x and deciding to
strip trailing zeros. You have to decide which decimal place to
round to.
No your answer showed how to strp trailing zeros from a buffer.
The difficult part of the question is how to convert the
floating point numbers into a string in a buffer.
(Note your example starts with a string, not
a floating point number)

I think it was pretty close.

int main(void)
{
char buffer[100];

sprintf(buffer, "%f", 2.19994019993);
puts(removeTralingZeros(buffer));
return 0;
}

I get 2.19994
 
W

William Hughes

pete said:
William said:
pemo wrote:
int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}

This only answers one part of the question
(and that the easy part).

Assume that the floating point number x, represents
the rational 2.19994019993

Should this print out as

2.2
2.1999
2.19994
2.1999402
2.1999401999

or

2.19994019993

This question cannot be answered
by merely looking at x and deciding to
strip trailing zeros. You have to decide which decimal place to
round to.
No your answer showed how to strp trailing zeros from a buffer.
The difficult part of the question is how to convert the
floating point numbers into a string in a buffer.
(Note your example starts with a string, not
a floating point number)

I think it was pretty close.

int main(void)
{
char buffer[100];

sprintf(buffer, "%f", 2.19994019993);
puts(removeTralingZeros(buffer));
return 0;
}

I get 2.19994

And what makes you think this is the "right" answer?
(note as well that you almost certainly do not sprintf
a floating point number that represents the rational 2.19994019993.
The compiler must convert the string 2.19994019993
to a floating point representation (a double) and it is very
unlikely that a double that represents 2.19994019993
exaclty exists.)

-William Hughes
 
C

Chris Torek

[topic drift, but still on-topic if we ignore the gcc extension]

BTW, I originally used a ? : in removeTralingZeros - it worked, but I got a
gcc warning:
[snippage]
buffer == '0' && noughtPointer == NULL ? noughtPointer =
&buffer : noughtPointer = NULL;


Or, equivalently:

a ? b = c : b = d;

If you examine the grammar in the C Standards, and use it to
determine the (single) allowable parse for the above, you will find
that it means the same thing as:

(a ? b = c : b) = d;

This is why you got a diagnostic: this is not valid C code.
[Warning] use of conditional expressions as lvalues is deprecated

(I cannot explain why it compiled at all -- gcc's ?:-as-lvalue
extension should not permit this unless the two colon-separated
operands are both lvalues. That is, gcc used to allow (a?b:c)=d,
with the "obvious" meaning. This extension is now deprecated
even in GNUC.)

Note that, if you do mean (and write):

a ? (b = c) : (b = d);

parentheses are not *required* around the "b = c" part, because
there is only one way to parse this -- the ?: expression *requires*
the colon, so:

a ? b = c : (b = d);

cannot be "mistakenly" parsed as:

((a ? b) = c) : ...;
I thought an lvalue was something on the left of an assignment operator?

In C89, an lvalue is well-defined (though not quite "properly"
defined, hence the C99 change) as "an expression that designates
an object". In C99, the definition was adjusted at the last minute
to fix a flaw, and the resulting definition is completely useless:
in C99, 3 is an "lvalue".

For these reasons, I prefer to distinguish between "objects" and
"values", where "object" means essentially what C89 uses the word
"lvalue" to describe. Assignment operators need an object (and
not a value) on the left. Using this terminology, Standard C always
has the result of any ?: expression being a value (not an object),
while GNUC has a now-deprecated extension in which the result of
a ?: expression is an object if and only if the second and third
operands are both objects.
 
P

pemo

pete said:
William said:
pemo wrote:
int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}

This only answers one part of the question
(and that the easy part).

Assume that the floating point number x, represents
the rational 2.19994019993

Should this print out as

2.2
2.1999
2.19994
2.1999402
2.1999401999

or

2.19994019993

This question cannot be answered
by merely looking at x and deciding to
strip trailing zeros. You have to decide which decimal place to
round to.
No your answer showed how to strp trailing zeros from a buffer.
The difficult part of the question is how to convert the
floating point numbers into a string in a buffer.
(Note your example starts with a string, not
a floating point number)

I think it was pretty close.

int main(void)
{
char buffer[100];

sprintf(buffer, "%f", 2.19994019993);
puts(removeTralingZeros(buffer));
return 0;
}

I get 2.19994

I get the same - but I think that's odd, as the way I thought I wrote the
function, it *should* return 2.19994019993, i.e., not trailing zeros to
remove.

However, I get the same result as you.

Upon further investigation, I find that if I puts(buffer) after the sprintf,
I only get 2.199940 as output - instead of 2.1999401993 - and - try as I
might just now, I don't seem to be able to get the full output either, e.g.,
F, lf, all seem to result in sprintf giving the same result.

So, the code seems to work as detailed - it's just that buffer contains
2.199940 when removeTralingZeros gets to look at it.
 
W

William Hughes

pemo said:
pete said:
William said:
pemo wrote:

pemo wrote:
int main(void)
{
char buffer[100];

// User input?
//
strcpy(&buffer[0], "3.14000100");

puts(removeTralingZeros(&buffer[0]));

getchar();

return 0;
}

This only answers one part of the question
(and that the easy part).

Assume that the floating point number x, represents
the rational 2.19994019993

Should this print out as

2.2
2.1999
2.19994
2.1999402
2.1999401999

or

2.19994019993

This question cannot be answered
by merely looking at x and deciding to
strip trailing zeros. You have to decide which decimal place to
round to.
No your answer showed how to strp trailing zeros from a buffer.
The difficult part of the question is how to convert the
floating point numbers into a string in a buffer.
(Note your example starts with a string, not
a floating point number)

I think it was pretty close.

int main(void)
{
char buffer[100];

sprintf(buffer, "%f", 2.19994019993);
puts(removeTralingZeros(buffer));
return 0;
}

I get 2.19994

I get the same - but I think that's odd, as the way I thought I wrote the
function, it *should* return 2.19994019993, i.e., not trailing zeros to
remove.

However, I get the same result as you.

Upon further investigation, I find that if I puts(buffer) after the sprintf,
I only get 2.199940 as output - instead of 2.1999401993 - and - try as I
might just now, I don't seem to be able to get the full output either, e.g.,
F, lf, all seem to result in sprintf giving the same result.

So, the code seems to work as detailed - it's just that buffer contains
2.199940 when removeTralingZeros gets to look at it.

This is because the default precision of all the formats you used
is 6 decimal places and 2.19994019993 rounded to six decimal
places is 2.199940 (in practice the approximation used by the
double variable will be much more than good enough, and I am
no sure but I think this is even follows from the standard). If you
want
the "full" output, specify a precison field (e.g %30.25f). But don't
be
surprised if the output is not 2.1999401993 (to get this try something
like %13.10f).
-William Hughes
 
M

Mark McIntyre

text, not some funky binary format. I would run some kind of filter
over one or both of the input files, converting any floating-point
constants to a common form, and then run diff on the result. C wouldn't
be my first choice of language to implement the filter.

Excel is good for this. In fact, I'd do the entire compare in excel.
This is not something there's any point using C for.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,170
Messages
2,570,927
Members
47,469
Latest member
benny001

Latest Threads

Top