forum-msg-id-133143-edit

Original date:2018-11-01 21:20:33 Edited by: MarkB Subject: Can printf() be made smarter?

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) > 12845.810000

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

I know this works printf(fn,"%.2f\n",x) > 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) > 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,"%9g\n",x) >

Incidentally, this is weird: printf(fn,"%.3g\n",x) > 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) > _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.

Not Categorized, Please Help

Search



Quick Links

User menu

Not signed in.

Misc Menu