discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Inconsistent conversion of floating number to string at 7th significant digit

R
runsun
Tue, Nov 10, 2015 6:02 PM

This post is about how OpenScad type-casts a floating point number to a
string(str()) or displays it in the console (echo()). I.e., nothing to do
with the internal calculation. Observation is carried out with OpenSCAD
version 2015.06.21.nightly (git 68e41af) running on Linux Mint 17.

I. First we know that round() gets rid of 4, advances 5:

round(1.4) => 1
round(1.5) => 2
round(4.4) => 4
round(4.5) => 5
round(5.4) => 5
round(5.5) => 6

II. OpenScad displays only 6 significant digits. I would expect extra
significant digits to be treated as the way round() works, i.e., cut 4,
advance 5. But it is not:

II-1. Integer -- When extra significant digit is 5, simply cut away:

str(123456) = 123456
str(1234560) = 1.23456e+06  // Sci.Notation
str(1234564) = 1.23456e+06  // 4 gets cut
str(1234565) = 1.23456e+06  // Why not 1.23457 ?
str(1234566) = 1.23457e+06  // 6 advances

II-2. Float (>=1) -- Rounded up normally to 6 significant digits: cut 4,
advance 5:

str(1.123456)    = 1.12346
str(1.0123456)    = 1.01235
str(1.00123456)  = 1.00123
str(1.000123456)  = 1.00012
str(1.0000123456) = 1.00001

II-3. Float (<1) -- 5 sometimes cut, sometimes advances:

str(0.1234565)    = 0.123456  // Why is 5 cut?
str(0.01234565)    = 0.0123456  // Why is 5 cut?
str(0.001234565)  = 0.00123456  // Why is 5 cut?
str(0.0001234565)  = 0.000123457  // 5 advances
str(0.00001234565) = 1.23456e-05  // Why is 5 cut?

III. This section is to test 6 digits + a 5, like 0.1111115, 0.2222225, etc,
and multiply them with 0.1 repeatedly. It appears that the extra-5 is
treated in an irregular manner:

str(0.1111115)    = 0.111112
str(0.01111115)    = 0.0111112
str(0.001111115)  = 0.00111111  // Why is 5 cut?
str(0.0001111115)  = 0.000111111  // Why is 5 cut?
str(0.00001111115) = 1.11111e-05  // Why is 5 cut?

str(0.2222225)    = 0.222222  // Why is 5 cut?
str(0.02222225)    = 0.0222222  // Why is 5 cut?
str(0.002222225)  = 0.00222222  // Why is 5 cut?
str(0.0002222225)  = 0.000222223
str(0.00002222225) = 2.22222e-05  // Why is 5 cut?

str(0.3333335)    = 0.333334
str(0.03333335)    = 0.0333333  // Why is 5 cut?
str(0.003333335)  = 0.00333334
str(0.0003333335)  = 0.000333334
str(0.00003333335) = 3.33333e-05  // Why is 5 cut?

str(0.4444445)    = 0.444445
str(0.04444445)    = 0.0444445
str(0.004444445)  = 0.00444444  // Why is 5 cut?
str(0.0004444445)  = 0.000444445
str(0.00004444445) = 4.44445e-05  // Why is 5 cut?

str(0.5555555)    = 0.555555  // Why is 5 cut?
str(0.05555555)    = 0.0555556
str(0.005555555)  = 0.00555556
str(0.0005555555)  = 0.000555555  // Why is 5 cut?
str(0.00005555555) = 5.55555e-05  // Why is 5 cut?

str(0.6666665)    = 0.666667
str(0.06666665)    = 0.0666666  // Why is 5 cut?
str(0.006666665)  = 0.00666666  // Why is 5 cut?
str(0.0006666665)  = 0.000666666  // Why is 5 cut?
str(0.00006666665) = 6.66667e-05

str(0.7777775)    = 0.777778
str(0.07777775)    = 0.0777778
str(0.007777775)  = 0.00777777  // Why is 5 cut?
str(0.0007777775)  = 0.000777777  // Why is 5 cut?
str(0.00007777775) = 7.77777e-05  // Why is 5 cut?

str(0.8888885)    = 0.888888  // Why is 5 cut?
str(0.08888885)    = 0.0888889
str(0.008888885)  = 0.00888888  // Why is 5 cut?
str(0.0008888885)  = 0.000888888  // Why is 5 cut?
str(0.00008888885) = 8.88888e-05  // Why is 5 cut?

str(0.9999995)    = 1
str(0.09999995)    = 0.1
str(0.009999995)  = 0.00999999  // Why is 5 cut?
str(0.0009999995)  = 0.001
str(0.00009999995) = 0.0001

IV. In this observation, 7 digits of 5 (5555555) is multiplied by pow(10,n).
Again, this shows the extra-5 is treated unpredictably:

str(5555555000)  = 5.55556e+09
str(555555500)    = 5.55556e+08
str(55555550)    = 5.55556e+07
str(5555555)      = 5.55556e+06
str(5.555555)    = 5.55556
str(0.5555555)    = 0.555555  // Why is 5 cut?
str(0.05555555)  = 0.0555556
str(0.005555555)  = 0.00555556
str(0.0005555555) = 0.000555555  // Why is 5 cut?
str(0.00005555555)= 5.55555e-05  // Why is 5 cut?


$  Runsun Pan, PhD

$ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git );

$ tips: hash( 1 , 2 ), sweep , var , lerp , animGif

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

This post is about how OpenScad *type-casts* a floating point number to a string(str()) or *displays* it in the console (echo()). I.e., nothing to do with the internal calculation. Observation is carried out with OpenSCAD version 2015.06.21.nightly (git 68e41af) running on Linux Mint 17. I. First we know that round() gets rid of 4, advances 5: > round(1.4) => 1 > round(1.5) => 2 > round(4.4) => 4 > round(4.5) => 5 > round(5.4) => 5 > round(5.5) => 6 II. OpenScad displays only 6 significant digits. I would expect extra significant digits to be treated as the way round() works, i.e., cut 4, advance 5. But it is not: II-1. Integer -- When extra significant digit is 5, simply cut away: > str(123456) = 123456 > str(1234560) = 1.23456e+06 // Sci.Notation > str(1234564) = 1.23456e+06 // 4 gets cut > str(1234565) = 1.23456e+06 // Why not 1.23457 ? > str(1234566) = 1.23457e+06 // 6 advances II-2. Float (>=1) -- Rounded up normally to 6 significant digits: cut 4, advance 5: > str(1.123456) = 1.12346 > str(1.0123456) = 1.01235 > str(1.00123456) = 1.00123 > str(1.000123456) = 1.00012 > str(1.0000123456) = 1.00001 II-3. Float (<1) -- 5 sometimes cut, sometimes advances: > str(0.1234565) = 0.123456 // Why is 5 cut? > str(0.01234565) = 0.0123456 // Why is 5 cut? > str(0.001234565) = 0.00123456 // Why is 5 cut? > str(0.0001234565) = 0.000123457 // 5 advances > str(0.00001234565) = 1.23456e-05 // Why is 5 cut? III. This section is to test 6 digits + a 5, like 0.1111115, 0.2222225, etc, and multiply them with 0.1 repeatedly. It appears that the extra-5 is treated in an irregular manner: > str(0.1111115) = 0.111112 > str(0.01111115) = 0.0111112 > str(0.001111115) = 0.00111111 // Why is 5 cut? > str(0.0001111115) = 0.000111111 // Why is 5 cut? > str(0.00001111115) = 1.11111e-05 // Why is 5 cut? > str(0.2222225) = 0.222222 // Why is 5 cut? > str(0.02222225) = 0.0222222 // Why is 5 cut? > str(0.002222225) = 0.00222222 // Why is 5 cut? > str(0.0002222225) = 0.000222223 > str(0.00002222225) = 2.22222e-05 // Why is 5 cut? > str(0.3333335) = 0.333334 > str(0.03333335) = 0.0333333 // Why is 5 cut? > str(0.003333335) = 0.00333334 > str(0.0003333335) = 0.000333334 > str(0.00003333335) = 3.33333e-05 // Why is 5 cut? > str(0.4444445) = 0.444445 > str(0.04444445) = 0.0444445 > str(0.004444445) = 0.00444444 // Why is 5 cut? > str(0.0004444445) = 0.000444445 > str(0.00004444445) = 4.44445e-05 // Why is 5 cut? > str(0.5555555) = 0.555555 // Why is 5 cut? > str(0.05555555) = 0.0555556 > str(0.005555555) = 0.00555556 > str(0.0005555555) = 0.000555555 // Why is 5 cut? > str(0.00005555555) = 5.55555e-05 // Why is 5 cut? > str(0.6666665) = 0.666667 > str(0.06666665) = 0.0666666 // Why is 5 cut? > str(0.006666665) = 0.00666666 // Why is 5 cut? > str(0.0006666665) = 0.000666666 // Why is 5 cut? > str(0.00006666665) = 6.66667e-05 > str(0.7777775) = 0.777778 > str(0.07777775) = 0.0777778 > str(0.007777775) = 0.00777777 // Why is 5 cut? > str(0.0007777775) = 0.000777777 // Why is 5 cut? > str(0.00007777775) = 7.77777e-05 // Why is 5 cut? > str(0.8888885) = 0.888888 // Why is 5 cut? > str(0.08888885) = 0.0888889 > str(0.008888885) = 0.00888888 // Why is 5 cut? > str(0.0008888885) = 0.000888888 // Why is 5 cut? > str(0.00008888885) = 8.88888e-05 // Why is 5 cut? > str(0.9999995) = 1 > str(0.09999995) = 0.1 > str(0.009999995) = 0.00999999 // Why is 5 cut? > str(0.0009999995) = 0.001 > str(0.00009999995) = 0.0001 IV. In this observation, 7 digits of 5 (5555555) is multiplied by pow(10,n). Again, this shows the extra-5 is treated unpredictably: > str(5555555000) = 5.55556e+09 > str(555555500) = 5.55556e+08 > str(55555550) = 5.55556e+07 > str(5555555) = 5.55556e+06 > str(5.555555) = 5.55556 > str(0.5555555) = 0.555555 // Why is 5 cut? > str(0.05555555) = 0.0555556 > str(0.005555555) = 0.00555556 > str(0.0005555555) = 0.000555555 // Why is 5 cut? > str(0.00005555555)= 5.55555e-05 // Why is 5 cut? ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git ); $ tips: hash( 1 , 2 ), sweep , var , lerp , animGif -- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350.html Sent from the OpenSCAD mailing list archive at Nabble.com.
C
clothbot
Tue, Nov 10, 2015 6:31 PM

This appears to be the code in question, called when converting doubles into
strings:

https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238

The key is this comment:

// attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD.
// see https://github.com/openscad/openscad/issues/158

That https://github.com/openscad/openscad/issues/158 contains details about
the thought-process that went into it.

Andrew.

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14354.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

This appears to be the code in question, called when converting doubles into strings: https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238 The key is this comment: // attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD. // see https://github.com/openscad/openscad/issues/158 That https://github.com/openscad/openscad/issues/158 contains details about the thought-process that went into it. Andrew. -- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14354.html Sent from the OpenSCAD mailing list archive at Nabble.com.
MK
Marius Kintel
Tue, Nov 10, 2015 6:42 PM

On Nov 10, 2015, at 13:31 PM, clothbot andrew@plumb.org wrote:

That https://github.com/openscad/openscad/issues/158 contains details about
the thought-process that went into it.

FYI: The test framework now has a better way of dealing with cross-platform rounding differences, so that aspect of the problem isn’t an issue any longer.

-Marius

> On Nov 10, 2015, at 13:31 PM, clothbot <andrew@plumb.org> wrote: > > That https://github.com/openscad/openscad/issues/158 contains details about > the thought-process that went into it. > FYI: The test framework now has a better way of dealing with cross-platform rounding differences, so that aspect of the problem isn’t an issue any longer. -Marius
R
runsun
Wed, Nov 11, 2015 9:04 PM

@clothbot: Thx for the links. After reviewing them, however, I do believe
this is a different issue. What bothers me is not "how many digits" in
specific cases (like 8 vs 8.0000000004) nor "different platforms", but what
looks like a totally irregular manner of handling the number 5 --- sometimes
it is rounded up, sometimes it is rounded down, and for all the time I spent
in investigation, I couldn't figure out what rule OpenSCAD follows to decide
rounding up or down number 5.

clothbot wrote

This appears to be the code in question, called when converting doubles
into strings:

https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238

The key is this comment:

 // attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD.
 // see https://github.com/openscad/openscad/issues/158

That https://github.com/openscad/openscad/issues/158 contains details
about the thought-process that went into it.

Andrew.


$  Runsun Pan, PhD

$ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git );

$ tips: hash( 1 , 2 ), sweep , var , lerp , animGif

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14375.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

@clothbot: Thx for the links. After reviewing them, however, I do believe this is a different issue. What bothers me is not "how many digits" in specific cases (like 8 vs 8.0000000004) nor "different platforms", but what looks like a totally irregular manner of handling the number 5 --- sometimes it is rounded up, sometimes it is rounded down, and for all the time I spent in investigation, I couldn't figure out what rule OpenSCAD follows to decide rounding up or down number 5. clothbot wrote > This appears to be the code in question, called when converting doubles > into strings: > > https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238 > > The key is this comment: > > // attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD. > // see https://github.com/openscad/openscad/issues/158 > > That https://github.com/openscad/openscad/issues/158 contains details > about the thought-process that went into it. > > Andrew. ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git ); $ tips: hash( 1 , 2 ), sweep , var , lerp , animGif -- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14375.html Sent from the OpenSCAD mailing list archive at Nabble.com.
DM
doug moen
Thu, Nov 12, 2015 2:12 AM

The round(x) function rounds away from zero. So round(0.5) == 1 and
round(-0.5) == -1.

The conversion from floating point to string is, in my opinion, broken. I
wrote a long explanation of why it is broken, and what I'd like to do
instead, in an earlier post. I should create an issue for this.

But briefly, I would like the float->string conversion to produce the
shortest floating point literal that, when read, exactlly reproduces the
original floating point number. This means no information is thrown away.

On 11 November 2015 at 16:04, runsun runsun@gmail.com wrote:

@clothbot: Thx for the links. After reviewing them, however, I do believe
this is a different issue. What bothers me is not "how many digits" in
specific cases (like 8 vs 8.0000000004) nor "different platforms", but what
looks like a totally irregular manner of handling the number 5 ---
sometimes
it is rounded up, sometimes it is rounded down, and for all the time I
spent
in investigation, I couldn't figure out what rule OpenSCAD follows to
decide
rounding up or down number 5.

clothbot wrote

This appears to be the code in question, called when converting doubles
into strings:

https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238

The key is this comment:

 // attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD.
 // see https://github.com/openscad/openscad/issues/158

That https://github.com/openscad/openscad/issues/158 contains details
about the thought-process that went into it.

Andrew.


$  Runsun Pan, PhD

$ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 ,
git );

$ tips: hash( 1 , 2 ), sweep , var , lerp , animGif

--
View this message in context:
http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14375.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

The round(x) function rounds away from zero. So round(0.5) == 1 and round(-0.5) == -1. The conversion from floating point to string is, in my opinion, broken. I wrote a long explanation of why it is broken, and what I'd like to do instead, in an earlier post. I should create an issue for this. But briefly, I would like the float->string conversion to produce the shortest floating point literal that, when read, exactlly reproduces the original floating point number. This means no information is thrown away. On 11 November 2015 at 16:04, runsun <runsun@gmail.com> wrote: > @clothbot: Thx for the links. After reviewing them, however, I do believe > this is a different issue. What bothers me is not "how many digits" in > specific cases (like 8 vs 8.0000000004) nor "different platforms", but what > looks like a totally irregular manner of handling the number 5 --- > sometimes > it is rounded up, sometimes it is rounded down, and for all the time I > spent > in investigation, I couldn't figure out what rule OpenSCAD follows to > decide > rounding up or down number 5. > > > clothbot wrote > > This appears to be the code in question, called when converting doubles > > into strings: > > > > https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238 > > > > The key is this comment: > > > > // attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD. > > // see https://github.com/openscad/openscad/issues/158 > > > > That https://github.com/openscad/openscad/issues/158 contains details > > about the thought-process that went into it. > > > > Andrew. > > > > > > ----- > > $ Runsun Pan, PhD > > $ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , > git ); > > $ tips: hash( 1 , 2 ), sweep , var , lerp , animGif > > > > > > > -- > View this message in context: > http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14375.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
C
ctchin
Thu, Nov 12, 2015 4:56 AM

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14389.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

-- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14389.html Sent from the OpenSCAD mailing list archive at Nabble.com.
C
ctchin
Thu, Nov 12, 2015 5:16 AM

doug.moen wrote

The conversion from floating point to string is, in my opinion, broken. I
wrote a long explanation of why it is broken, and what I'd like to do
instead, in an earlier post. I should create an issue for this.

Consider the many many things (some are quite challenging) that
still need adding/fixing/improving in OpenSCAD, I'm not sure str(n)
is high (or even mid-) priority.

It seems almost easy to just port sprintf() to OpenSCAD and that's
that.  But in an odd way, I almost relish the various handicaps OpenSCAD
throw at us.  The subtle message is: DON'T use OpenSCAD for
conventional programming, don't do text processing (don't even dream
about adding regular expression to OpenSCAD), don't do general
file I/O (fopen, fread, fwrite, fclose), don't do advanced computations (I
was
toying with the masochistic(???)  idea of writing a matrix inversion
algorithm
in OpenSCAD).

Sticks to making solids (STL) on OpenSCAD.  A true geek would just mix-
language program (Java+OpenSCAD) to solve his practical problems and
leaving the masochism (matrix inversion in OpenSCAD) to the nut jobs.

(hmmm I am assuming no one had actually done it... have I called some
very smart person a nut job? ... oh wait... it seems really probably
possible
to write it... eh...)

(oops sorry for empty post previous)

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14391.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

doug.moen wrote > The conversion from floating point to string is, in my opinion, broken. I > wrote a long explanation of why it is broken, and what I'd like to do > instead, in an earlier post. I should create an issue for this. Consider the many many things (some are quite challenging) that still need adding/fixing/improving in OpenSCAD, I'm not sure str(n) is high (or even mid-) priority. It seems almost easy to just port sprintf() to OpenSCAD and that's that. But in an odd way, I almost relish the various handicaps OpenSCAD throw at us. The subtle message is: DON'T use OpenSCAD for conventional programming, don't do text processing (don't even dream about adding regular expression to OpenSCAD), don't do general file I/O (fopen, fread, fwrite, fclose), don't do advanced computations (I was toying with the masochistic(???) idea of writing a matrix inversion algorithm in OpenSCAD). Sticks to making solids (STL) on OpenSCAD. A true geek would just mix- language program (Java+OpenSCAD) to solve his practical problems and leaving the masochism (matrix inversion in OpenSCAD) to the nut jobs. (hmmm I am assuming no one had actually done it... have I called some very smart person a nut job? ... oh wait... it seems really probably possible to write it... eh...) (oops sorry for empty post previous) -- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14391.html Sent from the OpenSCAD mailing list archive at Nabble.com.
TV
Tim V. Shaporev
Thu, Nov 12, 2015 11:11 AM

Advanced rounding algorithms may cast 0.5 to either 1 or 0 depending on
the preceding bit in the binary representation of the number.

See e.g. "Round half to even" https://en.wikipedia.org/wiki/Rounding

Just my $0.02
Tim

On 12.11.2015 0:04, runsun wrote:

@clothbot: Thx for the links. After reviewing them, however, I do believe
this is a different issue. What bothers me is not "how many digits" in
specific cases (like 8 vs 8.0000000004) nor "different platforms", but what
looks like a totally irregular manner of handling the number 5 --- sometimes
it is rounded up, sometimes it is rounded down, and for all the time I spent
in investigation, I couldn't figure out what rule OpenSCAD follows to decide
rounding up or down number 5.

clothbot wrote

This appears to be the code in question, called when converting doubles
into strings:

https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238

The key is this comment:

  // attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD.
  // see https://github.com/openscad/openscad/issues/158

That https://github.com/openscad/openscad/issues/158 contains details
about the thought-process that went into it.

Andrew.


$  Runsun Pan, PhD

$ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git );

$ tips: hash( 1 , 2 ), sweep , var , lerp , animGif

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14375.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Advanced rounding algorithms may cast 0.5 to either 1 or 0 depending on the preceding bit in the binary representation of the number. See e.g. "Round half to even" https://en.wikipedia.org/wiki/Rounding Just my $0.02 Tim On 12.11.2015 0:04, runsun wrote: > @clothbot: Thx for the links. After reviewing them, however, I do believe > this is a different issue. What bothers me is not "how many digits" in > specific cases (like 8 vs 8.0000000004) nor "different platforms", but what > looks like a totally irregular manner of handling the number 5 --- sometimes > it is rounded up, sometimes it is rounded down, and for all the time I spent > in investigation, I couldn't figure out what rule OpenSCAD follows to decide > rounding up or down number 5. > > > clothbot wrote >> This appears to be the code in question, called when converting doubles >> into strings: >> >> https://github.com/openscad/openscad/blob/master/src/value.cc#L225-L238 >> >> The key is this comment: >> >> // attempt to emulate Qt's QString.sprintf("%g"); from old OpenSCAD. >> // see https://github.com/openscad/openscad/issues/158 >> >> That https://github.com/openscad/openscad/issues/158 contains details >> about the thought-process that went into it. >> >> Andrew. > > > > > > ----- > > $ Runsun Pan, PhD > > $ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git ); > > $ tips: hash( 1 , 2 ), sweep , var , lerp , animGif > > > > > > > -- > View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14375.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
DM
doug moen
Thu, Nov 12, 2015 1:05 PM

ctchin said "Consider the many many things (some are quite challenging) that
still need adding/fixing/improving in OpenSCAD, I'm not sure str(n)
is high (or even mid-) priority."

I agree, but I'm not saying that. OpenSCAD uses the same float->string
conversion everywhere, including the export to ASCII STL, and the export to
AMF. In the export case, severely truncating each float to 6 significant
digits often damages the mesh, so that OpenSCAD can't read STL files that
it itself has generated. (The conversion from CGAL rational numbers to
floats can also damage the mesh, but the float->string conversion is
responsible for most of the damage.) I'd like to fix this, and str(n) will
get fixed at the same time, as a bonus.

On 12 November 2015 at 00:16, ctchin c.t.chin@szu.edu.cn wrote:

doug.moen wrote

The conversion from floating point to string is, in my opinion, broken. I
wrote a long explanation of why it is broken, and what I'd like to do
instead, in an earlier post. I should create an issue for this.

Consider the many many things (some are quite challenging) that
still need adding/fixing/improving in OpenSCAD, I'm not sure str(n)
is high (or even mid-) priority.

It seems almost easy to just port sprintf() to OpenSCAD and that's
that.  But in an odd way, I almost relish the various handicaps OpenSCAD
throw at us.  The subtle message is: DON'T use OpenSCAD for
conventional programming, don't do text processing (don't even dream
about adding regular expression to OpenSCAD), don't do general
file I/O (fopen, fread, fwrite, fclose), don't do advanced computations (I
was
toying with the masochistic(???)  idea of writing a matrix inversion
algorithm
in OpenSCAD).

Sticks to making solids (STL) on OpenSCAD.  A true geek would just mix-
language program (Java+OpenSCAD) to solve his practical problems and
leaving the masochism (matrix inversion in OpenSCAD) to the nut jobs.

(hmmm I am assuming no one had actually done it... have I called some
very smart person a nut job? ... oh wait... it seems really probably
possible
to write it... eh...)

(oops sorry for empty post previous)

--
View this message in context:
http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14391.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

ctchin said "Consider the many many things (some are quite challenging) that still need adding/fixing/improving in OpenSCAD, I'm not sure str(n) is high (or even mid-) priority." I agree, but I'm not saying that. OpenSCAD uses the same float->string conversion everywhere, including the export to ASCII STL, and the export to AMF. In the export case, severely truncating each float to 6 significant digits often damages the mesh, so that OpenSCAD can't read STL files that it itself has generated. (The conversion from CGAL rational numbers to floats can also damage the mesh, but the float->string conversion is responsible for most of the damage.) I'd like to fix this, and str(n) will get fixed at the same time, as a bonus. On 12 November 2015 at 00:16, ctchin <c.t.chin@szu.edu.cn> wrote: > doug.moen wrote > > The conversion from floating point to string is, in my opinion, broken. I > > wrote a long explanation of why it is broken, and what I'd like to do > > instead, in an earlier post. I should create an issue for this. > > Consider the many many things (some are quite challenging) that > still need adding/fixing/improving in OpenSCAD, I'm not sure str(n) > is high (or even mid-) priority. > > It seems almost easy to just port sprintf() to OpenSCAD and that's > that. But in an odd way, I almost relish the various handicaps OpenSCAD > throw at us. The subtle message is: DON'T use OpenSCAD for > conventional programming, don't do text processing (don't even dream > about adding regular expression to OpenSCAD), don't do general > file I/O (fopen, fread, fwrite, fclose), don't do advanced computations (I > was > toying with the masochistic(???) idea of writing a matrix inversion > algorithm > in OpenSCAD). > > Sticks to making solids (STL) on OpenSCAD. A true geek would just mix- > language program (Java+OpenSCAD) to solve his practical problems and > leaving the masochism (matrix inversion in OpenSCAD) to the nut jobs. > > (hmmm I am assuming no one had actually done it... have I called some > very smart person a nut job? ... oh wait... it seems really probably > possible > to write it... eh...) > > > (oops sorry for empty post previous) > > > > -- > View this message in context: > http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14391.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
R
runsun
Thu, Nov 12, 2015 5:12 PM

Tim V. Shaporev wrote

Advanced rounding algorithms may cast 0.5 to either 1 or 0 depending on
the preceding bit in the binary representation of the number.

See e.g. "Round half to even" https://en.wikipedia.org/wiki/Rounding

Just my $0.02
Tim

Thx, Tim. But this doesn't explain those examples I raised in the first
post, where the rounding of 5 is handled differently even the preceding
number is the same.


$  Runsun Pan, PhD

$ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git );

$ tips: hash( 1 , 2 ), sweep , var , lerp , animGif

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14406.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Tim V. Shaporev wrote > Advanced rounding algorithms may cast 0.5 to either 1 or 0 depending on > the preceding bit in the binary representation of the number. > > See e.g. "Round half to even" https://en.wikipedia.org/wiki/Rounding > > Just my $0.02 > Tim Thx, Tim. But this doesn't explain those examples I raised in the first post, where the rounding of 5 is handled differently even the preceding number is the same. ----- $ Runsun Pan, PhD $ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git ); $ tips: hash( 1 , 2 ), sweep , var , lerp , animGif -- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14406.html Sent from the OpenSCAD mailing list archive at Nabble.com.
C
ctchin
Thu, Nov 12, 2015 5:17 PM

doug.moen wrote

... the export to ASCII STL, and the export to
AMF. In the export case, severely truncating each float to 6 significant
digits often damages the mesh, so that OpenSCAD can't read STL files that
it itself has generated.

Oh... I wasn't aware of that issue (do apologize I haven't find time to go
over all old threads.)

But I still... question if it's not a bit of a red herring.  If OpenSCAD is
really designed for and
by 3D printing hobbyists and professionals, then does it serve meaningful
purpose to reproduce
better than 0.1PPM precision?  I am not asserting it is red herring, just
curious if someone really
come upon a real world issue arising from such level of inaccuracy.

As for OpenSCAD can't read STL it generates... again is that a high priority
issue?  Unlike
File->Save and File->Load, I can tolerate, even expect some loss when I
Export... and than
Import... some data, this is true in many apps, even MS Office.  Over the
year (not quite 2
years yet) I've designed some moderately elaborate shapes and never had
Slic3r reject a
design that OpenSCAD deemed valid.

I imagine other apps/devices (laser cutter?) similarly have been accepting
the STL's generated
by OpenSCAD.  IEEE floats are imperfect representation of physical world.
And text string
representation are further corruption of accuracy of IEEE floats.  That's
unavoidable.

We are quite happy to accept 20-side polygon as a circle, 100-ish-faces
polyhedron for a sphere.
There's easily inaccuracy of 1% in almost all of our designs.

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14407.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

doug.moen wrote > ... the export to ASCII STL, and the export to > AMF. In the export case, severely truncating each float to 6 significant > digits often damages the mesh, so that OpenSCAD can't read STL files that > it itself has generated. Oh... I wasn't aware of that issue (do apologize I haven't find time to go over all old threads.) But I still... question if it's not a bit of a red herring. If OpenSCAD is really designed for and by 3D printing hobbyists and professionals, then does it serve meaningful purpose to reproduce better than 0.1PPM precision? I am not asserting it is red herring, just curious if someone really come upon a real world issue arising from such level of inaccuracy. As for OpenSCAD can't read STL it generates... again is that a high priority issue? Unlike File->Save and File->Load, I can tolerate, even expect some loss when I Export... and than Import... some data, this is true in many apps, even MS Office. Over the year (not quite 2 years yet) I've designed some moderately elaborate shapes and never had Slic3r reject a design that OpenSCAD deemed valid. I imagine other apps/devices (laser cutter?) similarly have been accepting the STL's generated by OpenSCAD. IEEE floats are imperfect representation of physical world. And text string representation are further corruption of accuracy of IEEE floats. That's unavoidable. We are quite happy to accept 20-side polygon as a circle, 100-ish-faces polyhedron for a sphere. There's easily inaccuracy of 1% in almost all of our designs. -- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14407.html Sent from the OpenSCAD mailing list archive at Nabble.com.
AC
Alan Cox
Thu, Nov 12, 2015 6:29 PM

But I still... question if it's not a bit of a red herring.  If OpenSCAD is
really designed for and
by 3D printing hobbyists and professionals, then does it serve meaningful
purpose to reproduce
better than 0.1PPM precision?  I am not asserting it is red herring, just
curious if someone really
come upon a real world issue arising from such level of inaccuracy.

Probably not - and someone who understands the mathematics classes and
requirements of CGAL could change it to integer. I did look into it but
the requirements are complex and C++ is not my favourite language.

I imagine other apps/devices (laser cutter?) similarly have been accepting
the STL's generated
by OpenSCAD.  IEEE floats are imperfect representation of physical world.
And text string
representation are further corruption of accuracy of IEEE floats.  That's
unavoidable.

Text strings can be far more accuratethan IEEE float. The accuracy isn't
the problem however. The problem is that OpenSCAD does not follow the
accepted rules for creation of "correct" STL objects.

Properly written STL tools use a point dictionary to ensure that they do
not output an STL file with two different points with the same IEEE float
representation. If they find one they either juggle the points in the
dictionary the smallest amount possible to avoid a clash or cull what is
lost. Culling is hairy, juggling points far less so - especially if you
have the dictionary sorted in X Y and Z.

We are quite happy to accept 20-side polygon as a circle, 100-ish-faces
polyhedron for a sphere.
There's easily inaccuracy of 1% in almost all of our designs.

Quite a few of my designs have parts that won't work at 1% error, which
is fine because OpenSCAD can do more accuracy when needed. Please don't
assume just because you can tolerate 1% everyone can. When you have
moving parts or parts combined with etched metal pieces and/or mechanisms
the precision needed is often far higher.

Alan

> But I still... question if it's not a bit of a red herring. If OpenSCAD is > really designed for and > by 3D printing hobbyists and professionals, then does it serve meaningful > purpose to reproduce > better than 0.1PPM precision? I am not asserting it is red herring, just > curious if someone really > come upon a real world issue arising from such level of inaccuracy. Probably not - and someone who understands the mathematics classes and requirements of CGAL could change it to integer. I did look into it but the requirements are complex and C++ is not my favourite language. > I imagine other apps/devices (laser cutter?) similarly have been accepting > the STL's generated > by OpenSCAD. IEEE floats are imperfect representation of physical world. > And text string > representation are further corruption of accuracy of IEEE floats. That's > unavoidable. Text strings can be far more accuratethan IEEE float. The accuracy isn't the problem however. The problem is that OpenSCAD does not follow the accepted rules for creation of "correct" STL objects. Properly written STL tools use a point dictionary to ensure that they do not output an STL file with two different points with the same IEEE float representation. If they find one they either juggle the points in the dictionary the smallest amount possible to avoid a clash or cull what is lost. Culling is hairy, juggling points far less so - especially if you have the dictionary sorted in X Y and Z. > We are quite happy to accept 20-side polygon as a circle, 100-ish-faces > polyhedron for a sphere. > There's easily inaccuracy of 1% in almost all of our designs. Quite a few of my designs have parts that won't work at 1% error, which is fine because OpenSCAD can do more accuracy when needed. Please don't assume just because you can tolerate 1% everyone can. When you have moving parts or parts combined with etched metal pieces and/or mechanisms the precision needed is often far higher. Alan
MK
Marius Kintel
Thu, Nov 12, 2015 7:03 PM

On Nov 12, 2015, at 08:05 AM, doug moen doug@moens.org wrote:

I agree, but I'm not saying that. OpenSCAD uses the same float->string conversion everywhere, including the export to ASCII STL, and the export to AMF. In the export case, severely truncating each float to 6 significant digits often damages the mesh, so that OpenSCAD can't read STL files that it itself has generated.

We don’t - file exports are written with the default precision of C++’s stream operator. If you find any cases doing otherwise it would be considered a bug.

The primary reason why OpenSCAD sometimes cannot read back its STL output is that CGAL doesn’t support reading triangles without an area. This tends to happen when converting from CGAL’s internal representation to double, where some insanely small triangles get their coordinates shifted a tiny bit due to floating point accuracy limitations.
One solution, as mentioned earlier, could be to perform a topology-aware surface optimization to ensure all triangles have a valid area, but since CGAL is the most picky component and most other tools can handle zero-area triangles, this hasn’t been a priority.

-Marius

> On Nov 12, 2015, at 08:05 AM, doug moen <doug@moens.org> wrote: > > I agree, but I'm not saying that. OpenSCAD uses the same float->string conversion everywhere, including the export to ASCII STL, and the export to AMF. In the export case, severely truncating each float to 6 significant digits often damages the mesh, so that OpenSCAD can't read STL files that it itself has generated. We don’t - file exports are written with the default precision of C++’s stream operator. If you find any cases doing otherwise it would be considered a bug. The primary reason why OpenSCAD sometimes cannot read back its STL output is that CGAL doesn’t support reading triangles without an area. This tends to happen when converting from CGAL’s internal representation to double, where some insanely small triangles get their coordinates shifted a tiny bit due to floating point accuracy limitations. One solution, as mentioned earlier, could be to perform a topology-aware surface optimization to ensure all triangles have a valid area, but since CGAL is the most picky component and most other tools can handle zero-area triangles, this hasn’t been a priority. -Marius
C
ctchin
Fri, Nov 13, 2015 2:28 AM

Alan Cox wrote

Quite a few of my designs have parts that won't work at 1% error, which
is fine because OpenSCAD can do more accuracy when needed. Please don't
assume just because you can tolerate 1% everyone can.

I do not and I do not.

The level of accuracy I grew up with (very spoiled I was) was better than 1
mil
(25 um).  I'm constantly haggling with my 3D printer service provider to
squeeze more accuracy out of them.

But 25 um on parts of typically 5-50cm is only  50ppm, and that's about
the limit of a 20+ yr veteran machinist with a multi-millions dollar shop.

I challenge the notion that OpenSCAD number to string algorithm ever causes
a real world problem.

I have my pet peeve about OpenSCAD's numeric accuracy.  I feel strongly it
is
much more deserving of developer's precise time compared the
number-to-string
issue.  Perfect! there's already a thread for it, I will continue there...

--
View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14429.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Alan Cox wrote > Quite a few of my designs have parts that won't work at 1% error, which > is fine because OpenSCAD can do more accuracy when needed. Please don't > assume just because you can tolerate 1% everyone can. I do not and I do not. The level of accuracy I grew up with (very spoiled I was) was better than 1 mil (25 um). I'm constantly haggling with my 3D printer service provider to squeeze more accuracy out of them. But 25 um on parts of typically 5-50cm is only 50ppm, and that's about the limit of a 20+ yr veteran machinist with a multi-millions dollar shop. I challenge the notion that OpenSCAD number to string algorithm ever causes a real world problem. I have my pet peeve about OpenSCAD's numeric accuracy. I feel strongly it is much more deserving of developer's precise time compared the number-to-string issue. Perfect! there's already a thread for it, I will continue there... -- View this message in context: http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14429.html Sent from the OpenSCAD mailing list archive at Nabble.com.
PT
Philipp Tiefenbacher
Fri, Nov 13, 2015 11:47 AM

Hi?
In all cases given the number is not representable in base 2 (because base
2 has no prime factor 5 like base 10 which you gave your examples in) so
the ...5 becomes a ...4999smthng and that gets rounded down correctly.

This explains the "random" behaviour.

Greetings
Philipp
On Nov 12, 2015 6:13 PM, "runsun" runsun@gmail.com wrote:

Tim V. Shaporev wrote

Advanced rounding algorithms may cast 0.5 to either 1 or 0 depending on
the preceding bit in the binary representation of the number.

See e.g. "Round half to even" https://en.wikipedia.org/wiki/Rounding

Just my $0.02
Tim

Thx, Tim. But this doesn't explain those examples I raised in the first
post, where the rounding of 5 is handled differently even the preceding
number is the same.


$  Runsun Pan, PhD

$ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 ,
git );

$ tips: hash( 1 , 2 ), sweep , var , lerp , animGif

--
View this message in context:
http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14406.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Hi? In all cases given the number is not representable in base 2 (because base 2 has no prime factor 5 like base 10 which you gave your examples in) so the ...5 becomes a ...4999smthng and that gets rounded down correctly. This explains the "random" behaviour. Greetings Philipp On Nov 12, 2015 6:13 PM, "runsun" <runsun@gmail.com> wrote: > Tim V. Shaporev wrote > > Advanced rounding algorithms may cast 0.5 to either 1 or 0 depending on > > the preceding bit in the binary representation of the number. > > > > See e.g. "Round half to even" https://en.wikipedia.org/wiki/Rounding > > > > Just my $0.02 > > Tim > > Thx, Tim. But this doesn't explain those examples I raised in the first > post, where the rounding of 5 is handled differently even the preceding > number is the same. > > > > > ----- > > $ Runsun Pan, PhD > > $ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , > git ); > > $ tips: hash( 1 , 2 ), sweep , var , lerp , animGif > > > > > > > -- > View this message in context: > http://forum.openscad.org/Inconsistent-conversion-of-floating-number-to-string-at-7th-significant-digit-tp14350p14406.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
TV
Tim V. Shaporev
Fri, Nov 13, 2015 12:45 PM

On 12.11.2015 22:03, Marius Kintel wrote:

We don’t - file exports are written with the default precision of C++’s stream operator. If you find any cases doing otherwise it would be considered a bug.

???

char buf[32];
sprintf(buf, "%.16f", x);
cout << buf;

Better approach would be to specify output accuracy like
sprintf(buf, "%.*f", n, f);

where n is something like

if      (x >= 1e15) n = 0;
else if (x >= 1e14) n = 1;
else if (x >= 1e13) n = 2;
else if (x >= 1e12) n = 3;
else if (x >= 1e11) n = 4;
else if (x >= 1e10) n = 5;
else if (x >= 1000000000) n = 6;
else if (x >= 100000000) n = 7;
else if (x >= 10000000) n = 8;
else if (x >= 1000000) n = 9;
else if (x >= 100000) n = 10;
else if (x >= 10000) n = 11;
else if (x >= 1000) n = 12;
else if (x >= 100) n = 13;
else if (x >= 10) n = 14;
else if (x >= 1) n = 15;
else n = 16;

or more accurately
if (x >= 1e16)
sprintf(buf, "%.15g", x);
else {
register int n = 0;
if (x < 10000000) {
if (x < 1000) {
if (x < 10)
n = x < 1 ? 16 : 15;
else
n = x < 100 ? 14 : 13;
} else {
if (x < 100000)
n = x < 10000 ? 12 : 11;
else
n = x < 1000000 ? 10 : 9;
}
} else if (x < 1e15) {
if (x < 1e11) {
if (x < 1000000000)
n = x < 100000000 ? 8 : 7;
else
n = x < 1e10 ? 6 : 5;
} else {
if (x < 1e13)
n = x < 1e12 ? 4 : 3;
else
n = x < 1e14 ? 2 : 1;
}
}
sprintf(buf, "%.*f", n, x);
}

Does this make any sense?

Tim

On 12.11.2015 22:03, Marius Kintel wrote: > We don’t - file exports are written with the default precision of C++’s stream operator. If you find any cases doing otherwise it would be considered a bug. ??? char buf[32]; sprintf(buf, "%.16f", x); cout << buf; Better approach would be to specify output accuracy like sprintf(buf, "%.*f", n, f); where n is something like if (x >= 1e15) n = 0; else if (x >= 1e14) n = 1; else if (x >= 1e13) n = 2; else if (x >= 1e12) n = 3; else if (x >= 1e11) n = 4; else if (x >= 1e10) n = 5; else if (x >= 1000000000) n = 6; else if (x >= 100000000) n = 7; else if (x >= 10000000) n = 8; else if (x >= 1000000) n = 9; else if (x >= 100000) n = 10; else if (x >= 10000) n = 11; else if (x >= 1000) n = 12; else if (x >= 100) n = 13; else if (x >= 10) n = 14; else if (x >= 1) n = 15; else n = 16; or more accurately if (x >= 1e16) sprintf(buf, "%.15g", x); else { register int n = 0; if (x < 10000000) { if (x < 1000) { if (x < 10) n = x < 1 ? 16 : 15; else n = x < 100 ? 14 : 13; } else { if (x < 100000) n = x < 10000 ? 12 : 11; else n = x < 1000000 ? 10 : 9; } } else if (x < 1e15) { if (x < 1e11) { if (x < 1000000000) n = x < 100000000 ? 8 : 7; else n = x < 1e10 ? 6 : 5; } else { if (x < 1e13) n = x < 1e12 ? 4 : 3; else n = x < 1e14 ? 2 : 1; } } sprintf(buf, "%.*f", n, x); } Does this make any sense? Tim
AC
Alan Cox
Fri, Nov 13, 2015 1:07 PM

Better approach would be to specify output accuracy like
sprintf(buf, "%.*f", n, f);

where n is something like

What is wrong  "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the
other mucking around should be needed.

Alan

> Better approach would be to specify output accuracy like > sprintf(buf, "%.*f", n, f); > > where n is something like What is wrong "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the other mucking around should be needed. Alan
TV
Tim V. Shaporev
Fri, Nov 13, 2015 1:16 PM

DBL_DECIMAL_DIG may be?

On 13.11.2015 16:07, Alan Cox wrote:

Better approach would be to specify output accuracy like
sprintf(buf, "%.*f", n, f);

where n is something like

What is wrong  "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the
other mucking around should be needed.

Alan


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

DBL_DECIMAL_DIG may be? On 13.11.2015 16:07, Alan Cox wrote: >> Better approach would be to specify output accuracy like >> sprintf(buf, "%.*f", n, f); >> >> where n is something like > > What is wrong "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the > other mucking around should be needed. > > Alan > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
TV
Tim V. Shaporev
Fri, Nov 13, 2015 4:44 PM

After some thinking I remembered why I imagined such piece of code :-)
to truncate trailing zeros (see at the end):

if (x >= 1e16)
sprintf(buf, "%.15g", x);
else {
register int n = 0;
if (x < 10000000) {
if (x < 1000) {
if (x < 10)
n = x < 1 ? 16 : 15;
else
n = x < 100 ? 14 : 13;
} else {
if (x < 100000)
n = x < 10000 ? 12 : 11;
else
n = x < 1000000 ? 10 : 9;
}
} else if (x < 1e15) {
if (x < 1e11) {
if (x < 1000000000)
n = x < 100000000 ? 8 : 7;
else
n = x < 1e10 ? 6 : 5;
} else {
if (x < 1e13)
n = x < 1e12 ? 4 : 3;
else
n = x < 1e14 ? 2 : 1;
}
}
sprintf(buf, "%.*f", n, x);
if (n > 0) {
for (i=strlen(buf); n && '0' == buf[n];) --n;
if (n>0 && '.' == buf[n]) --n;
buf[n] = '\0';
}
}

On 13.11.2015 16:07, Alan Cox wrote:

Better approach would be to specify output accuracy like
sprintf(buf, "%.*f", n, f);

where n is something like

What is wrong  "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the
other mucking around should be needed.

Alan


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

After some thinking I remembered why I imagined such piece of code :-) to truncate trailing zeros (see at the end): if (x >= 1e16) sprintf(buf, "%.15g", x); else { register int n = 0; if (x < 10000000) { if (x < 1000) { if (x < 10) n = x < 1 ? 16 : 15; else n = x < 100 ? 14 : 13; } else { if (x < 100000) n = x < 10000 ? 12 : 11; else n = x < 1000000 ? 10 : 9; } } else if (x < 1e15) { if (x < 1e11) { if (x < 1000000000) n = x < 100000000 ? 8 : 7; else n = x < 1e10 ? 6 : 5; } else { if (x < 1e13) n = x < 1e12 ? 4 : 3; else n = x < 1e14 ? 2 : 1; } } sprintf(buf, "%.*f", n, x); if (n > 0) { for (i=strlen(buf); n && '0' == buf[n];) --n; if (n>0 && '.' == buf[n]) --n; buf[n] = '\0'; } } On 13.11.2015 16:07, Alan Cox wrote: >> Better approach would be to specify output accuracy like >> sprintf(buf, "%.*f", n, f); >> >> where n is something like > > What is wrong "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the > other mucking around should be needed. > > Alan > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
DM
doug moen
Fri, Nov 13, 2015 5:04 PM

The best way for OpenSCAD to print floating point numbers is using the
algorithm from the paper "How To Print Floating Point Numbers Accurately".
That's what Python uses. That's what Javascript uses. That's what most
languages use, except...

...it's impossible to do this in C or C++ using only the standard library.
You need to use a separate open source library. The printf %g format is
bullshit, since it throws away most of the information in the number. You
can't do it with printf or std::stream:<<. The C and C++ standards are
rubbish for not supporting this important feature.

More details in my earlier post:
http://lists.openscad.org/pipermail/discuss_lists.openscad.org/2015-August/003078.html

Maybe I'll try implementing this on the weekend.

On 13 November 2015 at 08:07, Alan Cox alan@lxorguk.ukuu.org.uk wrote:

Better approach would be to specify output accuracy like
sprintf(buf, "%.*f", n, f);

where n is something like

What is wrong  "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the
other mucking around should be needed.

Alan


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

The best way for OpenSCAD to print floating point numbers is using the algorithm from the paper "How To Print Floating Point Numbers Accurately". That's what Python uses. That's what Javascript uses. That's what most languages use, except... ...it's impossible to do this in C or C++ using only the standard library. You need to use a separate open source library. The printf %g format is bullshit, since it throws away most of the information in the number. You can't do it with printf or std::stream:<<. The C and C++ standards are rubbish for not supporting this important feature. More details in my earlier post: http://lists.openscad.org/pipermail/discuss_lists.openscad.org/2015-August/003078.html Maybe I'll try implementing this on the weekend. On 13 November 2015 at 08:07, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote: > > Better approach would be to specify output accuracy like > > sprintf(buf, "%.*f", n, f); > > > > where n is something like > > What is wrong "%.*g" with FLT_DECIMAL_DIG (from float.h). None of the > other mucking around should be needed. > > Alan > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >