Can printf() be made smarter?

new topic     » topic index » view thread      » older message » newer message

Hey all, I'm a long time lurker and hobby programmer but new to posting.

I'm working on a program to read a text file, process the file and write results in a text file for another program to read. The input file, an AutoCad .dxf, contains a lot of integers and floats in text format with varying decimal places depending on the drawing details. Ideally my program would write some of these numbers in the output file with the same precision that they are read, i.e. with the same number of decimal places.

That's where the fun starts - how to get printf() to write the number of places the float contains.

Example: the number 12845.81. A harmless number read from the dxf, contained in an EU atom x. Let's write it in the output file (all in EU version 4.0, in case it matters):
printf(fn,"%f\n",x) returns 12845.810000

OK so let's try restricting the field width (yeah, I know it shouldn't work)
printf(fn,"%8f\n",x) returns 12845.810000

I know this works
printf(fn,"%.2f\n",x) returns 12845.81
but what if the number had 3 or more decimal places, which some in this file do?

So we give up on %f, which by default always shows 6 decimal places unless told otherwise, and try %g
printf(fn,"%g\n",x) returns 12845.8

What happened to the 1? %g seems to prefer 6 significant digits, even if that means losing significant decimal places. Why do I say this?
printf(fn,"%g\n",x) for x=128455.81 (note the bigger x) returns 128456 with no decimal places.

Lets 'encourage' it to include more digits (back to the original x):
printf(fn,"%8g\n",x) returns _12845.8 (where _ means space)

Incidentally, this is weird:
printf(fn,"%.3g\n",x) returns 1.28e+04.
How is that the most appropriate way to display this number?

'Encouraging' it to expand the number out results in:
printf(fn,"%9.3g\n",x) returns _1.28e+04 (again, _ means space)

I conclude %g isn't very useful, or at least not reliable.

What to do? printf() is an EU inbuilt function so I can't see what it does in an include file, so I went to the C source files. I chased it as far as I could, to C's snprintf() in stdio.h, but I'm not a C programmer so probably missed something. It seems EU simply passes the printf() arguments direct to C's snprintf(), plus the internet told me C's printf("%f") by default returns 6 decimal places. So C is the culprit and Euphoria doesn't do anything to change it.

I know I can fix it by, for example, s = sprintf("%.16f",x) then a loop to delete trailing zeros from s and puts(fn,s). I'll probably include that in a function in my program, messy as it is. However, two questions:

1. Is there a better way to fix this with current Euphoria? This isn't important as I already have a strategy that will work, however I'm interested to see what people come up with.

2. Can Euphoria be made 'smarter' to fix C's lack of smarts with both %f and %g, perhaps in future versions? In general I think of Euphoria as a smarter C, where it overcomes some of C's significant shortcomings, so why not with this admittedly very minor 'problem' as well? I don't think I'm good enough with C to do it myself, although I could just yell "YOLO" and dive right in.......

Cheers, Mark. (edited because arrows turn following text to strikeout - who knew?)

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu