470,591 Members | 2,247 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,591 developers. It's quick & easy.

How to detect a double's significant digits

Hi all... How can I find out the number of significant digits (to the
right of the decimal place, that is) in a double? At least, I *think*
that's what I'm asking for. For instance:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7

Thanks in advance!
--Steve (mr************@hotmail.com)

Jul 19 '05 #1
29 4137
Significant digits are an accounting concept. As such, it is up to the
accountant to keep track of these as only she knows the precision of her
measurements.

Koan for the day:

What are the significant digits of 0.1?

Hint:
`0.1`

James
On Thursday 05 May 2005 10:37 am, so sayeth mrstephengross: Hi all... How can I find out the number of significant digits (to the
right of the decimal place, that is) in a double? At least, I *think*
that's what I'm asking for. For instance:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7

Thanks in advance!
--Steve (mr************@hotmail.com)


--
James Stroud, Ph.D.
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
Jul 19 '05 #2
So how can I get the kind of information I want then?

For example:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7

Any ideas?
--Steve

Jul 19 '05 #3
fl = 1.0002
x = str(fl)
pos = x.find('.')
print len( x[pos+1:] )
4

mrstephengross wrote:
Hi all... How can I find out the number of significant digits (to the
right of the decimal place, that is) in a double? At least, I *think*
that's what I'm asking for. For instance:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7

Thanks in advance!
--Steve (mr************@hotmail.com)


Jul 19 '05 #4
Ok, that won't work. First of all, str() is not a function. If I want
to convert the float into a string, the conversion function will have
to use some kind of numeric precision, which will screw things up.
Consider this:

float f = 1.004;
ostringstream s;
s << f;
cout << s.str();

The above code may produce "1.004", or "1.0040", or "1.00400",
depending on the stream's precision setting. I need a way to detect the
number of digits to the right of decimal point *prior* to doing any
kind of string conversion.

--Steve

Jul 19 '05 #5
mrstephengross wrote:
So how can I get the kind of information I want then?

For example:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7


Beware that this is probably only relevant if you have your numbers as
strings, not as floats:

py> 0.103
0.10299999999999999

But, assuming you have your numbers as strings, I would suggest looking
at str.split() and len(). I'd give you an example, but this sounds
kinda like a homework assignment.

STeVe
Jul 19 '05 #6
mrstephengross wrote:
First of all, str() is not a function.
Yes it is.
float f = 1.004;
ostringstream s;
s << f;
cout << s.str();


This doesn't look like Python to me. Are you sure you're on the right
newsgroup?

STeVe
Jul 19 '05 #7
>But, assuming you have your numbers as strings, I would suggest
looking
at str.split() and len().

Well, the numbers are in fact stored as numbers, so string processing
won't work.
I'd give you an example, but this sounds kinda like a homework

assignment.

The task may sound like it comes from class, but I can assure you that
I am indeed a professional developer. I'm doing some rather intricate
text processing / rendering stuff these days, and C++ is unfortunately
none too handy for that sort of thing. Unfortunately, I have to use it
for the task.

Thanks,
--Steve

Jul 19 '05 #8
mrstephengross wrote:
Well, the numbers are in fact stored as numbers, so string processing
won't work.


What kind of numbers? Python floats?

STeVe
Jul 19 '05 #9
mrstephengross wrote:
But, assuming you have your numbers as strings, I would suggest


looking
at str.split() and len().

Well, the numbers are in fact stored as numbers, so string processing
won't work.


How about:

py> def digits(f):
.... return len(str(f).split('.')[1].rstrip('0'))
....
py> for f in [0.103, 0.1030, 0.0103, 0.010300]:
.... print f, digits(f)
....
0.103 3
0.103 3
0.0103 4
0.0103 4

I believe the rstrip is unnecessary because I think str() will never
produce additional following zeros, but you can guarantee it by calling
rstrip if you want.

Note that, for example, 0.103 and 0.1030 are identical as far as Python
is concerned, so I hope you're not hoping to show a difference between
these two...

STeVe
Jul 19 '05 #10
On 5 May 2005 10:37:00 -0700, mrstephengross <mr************@hotmail.com> wrote:
Hi all... How can I find out the number of significant digits (to the
right of the decimal place, that is) in a double? At least, I *think*
that's what I'm asking for. For instance:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7

Thanks in advance!
--Steve (mr************@hotmail.com)


I would say that each of these examples has three signficant figures.
Each of them can be expressed as:

1.03e+n

For any integer n.

The fact that you've only shown the cases where n \in {-1, -2, -3, -4,
-5 . . } doesn't change the generality of the answer.

Jul 19 '05 #11
On 2005-05-05, mrstephengross <mr************@hotmail.com> wrote:
But, assuming you have your numbers as strings, I would suggest looking
at str.split() and len().

Well, the numbers are in fact stored as numbers,


Then your question is in fact meaningless. The related
question that can be answered is "where is the least
significant '1' bit in the IEEE representation". If that's
useful information, the struct module will help you find it.
so string processing won't work.


That's the only way to answer the question you asked.
I'd give you an example, but this sounds kinda like a homework
assignment.


The task may sound like it comes from class, but I can assure
you that I am indeed a professional developer. I'm doing some
rather intricate text processing / rendering stuff these days,
and C++ is unfortunately none too handy for that sort of
thing. Unfortunately, I have to use it for the task.


--
Grant Edwards grante Yow! Hmmm... A hash-singer
at and a cross-eyed guy were
visi.com SLEEPING on a deserted
island, when...
Jul 19 '05 #12
>This doesn't look like Python to me. Are you sure you're on the right
newsgroup?

Er, ok, I'm an idiot. This was all supposed to be on comp.lang.c++, but
obviously I posted on the wrong one. Sorry for all the hassle. In
python, this stuff is a heck of a lot easier.

--Steve

Jul 19 '05 #13
Bollocks, works here.

That looks like Java!!! Aaaihh!

mrstephengross wrote:
Ok, that won't work. First of all, str() is not a function. If I want
to convert the float into a string, the conversion function will have
to use some kind of numeric precision, which will screw things up.
Consider this:

float f = 1.004;
ostringstream s;
s << f;
cout << s.str();

The above code may produce "1.004", or "1.0040", or "1.00400",
depending on the stream's precision setting. I need a way to detect the
number of digits to the right of decimal point *prior* to doing any
kind of string conversion.

--Steve


Jul 19 '05 #14
mrstephengross wrote:
This was all supposed to be on comp.lang.c++, but


You may still want to read the following thread on Python-Dev:
http://mail.python.org/pipermail/pyt...ch/043703.html

A link mentioned by Andrew Koenig may be helpful:
http://www.netlib.org/fp/

"""
file g_fmt.c
by David Gay
for ANSI C or C++ source for function g_fmt(char *, double):
, with help from dtoa, g_fmt(buf, x) sets buf to the shortest
, decimal string that correctly rounds to x and returns buf.
"""

Peter

Jul 19 '05 #15
"mrstephengross" wrote:
But, assuming you have your numbers as strings, I would suggest

looking
at str.split() and len().

Well, the numbers are in fact stored as numbers, so string processing
won't work.


if they're not strings, your question is meaningless. as others have
pointed out, the exact internal representation for 0.103 is more like
0.102999999999999994337862574411701643839478492736 81640625
which has a lot more than 3 digits...
I'd give you an example, but this sounds kinda like a homework

assignment.

The task may sound like it comes from class, but I can assure you that
I am indeed a professional developer.


well professional or not, you clearly need to refresh your floating point
skills. I suggest reading the following documents before proceeding:

http://docs.python.org/tut/node16.html
http://www.lahey.com/float.htm

</F>

Jul 19 '05 #16
On Thu, 05 May 2005 18:42:17 +0000, Charles Krug wrote:
On 5 May 2005 10:37:00 -0700, mrstephengross <mr************@hotmail.com>
wrote:
Hi all... How can I find out the number of significant digits (to the
right of the decimal place, that is) in a double? At least, I *think*
that's what I'm asking for. For instance:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7

Thanks in advance!
--Steve (mr************@hotmail.com)

I would say that each of these examples has three signficant figures. Each
of them can be expressed as:

1.03e+n

For any integer n.


You beat me to it.

Step one for mrstephengross is to *rigorously* define what he means by
"significant digits", then go from there. Since I think he mentioned
something about predicting how much space it will take to print out, my
suggestion is to run through whatever printing routines there are and get
a string out, the measure the string, as anything else will likely be
wrong. If that's not possible with the formatting library, you've already
lost; you'll have to completely correctly re-implement the formatting
library, and not only is that a major PITA, you almost never get it
bug-for-bug right...
Jul 19 '05 #17
Jeremy Bowers wrote:
Step one for mrstephengross is to *rigorously* define what he means by
"significant digits", then go from there. Since I think he mentioned
something about predicting how much space it will take to print out, my
suggestion is to run through whatever printing routines there are and get
a string out, the measure the string, as anything else will likely be
wrong. If that's not possible with the formatting library, you've already
lost; you'll have to completely correctly re-implement the formatting
library, and not only is that a major PITA, you almost never get it
bug-for-bug right...


Especially since all of his examples have the same number of significant
digits (3), as the term is usually meant. Zeroes to the right are
significant, not zeroes to the left.

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
What is it that shapes a species?
-- Louis Wu
Jul 19 '05 #18
On 2005-05-05, Jeremy Bowers <je**@jerf.org> wrote:
Since I think he mentioned something about predicting how much
space it will take to print out, my suggestion is to run
through whatever printing routines there are and get a string
out,


A step which will require him to tell the printing routine how
many digits he wants printed.

--
Grant Edwards grante Yow! FUN is never having
at to say you're SUSHI!!
visi.com
Jul 19 '05 #19
On 2005-05-05, Erik Max Francis <ma*@alcyone.com> wrote:
Especially since all of his examples have the same number of
significant digits (3), as the term is usually meant. Zeroes
to the right are significant, not zeroes to the left.


And only the person who performed the measurement knows how
many of the zeros to the right are significant.

--
Grant Edwards grante Yow! They don't hire
at PERSONAL PINHEADS,
visi.com Mr. Toad!
Jul 19 '05 #20
On 2005-05-05, mrstephengross <mr************@hotmail.com> wrote:
This doesn't look like Python to me. Are you sure you're on the right

newsgroup?

Er, ok, I'm an idiot. This was all supposed to be on
comp.lang.c++, but obviously I posted on the wrong one. Sorry
for all the hassle. In python, this stuff is a heck of a lot
easier.


No, it isn't. The question is equally meaningless in any
language.

--
Grant Edwards grante Yow! WHO sees a BEACH
at BUNNY sobbing on a SHAG
visi.com RUG?!
Jul 19 '05 #21
On Fri, 06 May 2005 02:44:43 +0000, Grant Edwards wrote:
On 2005-05-05, Jeremy Bowers <je**@jerf.org> wrote:
Since I think he mentioned something about predicting how much space it
will take to print out, my suggestion is to run through whatever
printing routines there are and get a string out,


A step which will require him to tell the printing routine how many digits
he wants printed.


Not necessarily; consider the str() of a float in Python, especially given
the "significant digits" aspect (it may be ill-defined, but I can think of
several well-defined ways to mean that, where str() embodies one of them).
The easiest way to tell how long the number will be when str prints it out
is to simply ask it.

In C++, this may be harder, as your output software may insist on
rendering everything directly, with no way to reach in and tell what it
did. Imagine the standard IOStreams, without the ability to stream into a
string. Now it's a lot harder to tell. So if you've got something "smart"
like the default str() in Python, you may not be able to tell in advance
what it is going to do, short of trying to manually reverse engineer it.
I've tried that a few times, and in each instance, I can get 95-99%... but
I never quite make it to 100%, usually because I find a bug somewhere and
can't figure out how to characterize and replicate it.

(The biggest of these so far was when I tried to reconstruct Tk's wrapping
in a text widget, so I could tell how many screen lines the given piece of
text I produced would consume, whereupon I discovered Tk didn't correctly
wrap all Unicode characters... it correctly (as far as I could see)
reported their widths, but happily let the characters run right off the
right edge of the widget under certain circumstances I could never
characterize without putting in even more effort than I cared to. The bugs
aren't always *important*, one can imagine the opposite problem of
wrapping a little too quickly, and it could be years before anyone notices
if it's just a few pixels off in the right direction, but it'll still
screw you up if you try to replicate it.)

Jul 19 '05 #22
Jeremy Bowers wrote:
Not necessarily; consider the str() of a float in Python, especially given
the "significant digits" aspect (it may be ill-defined, but I can think of
several well-defined ways to mean that, where str() embodies one of them).
The easiest way to tell how long the number will be when str prints it out
is to simply ask it.


Grant's point was that as significance is used in scientific studies,
there's no way to answer the question without having the number in
advance. If I say that the length of something is 1100 m, you don't
know whether I mean 1.1 x 10^3 m, 1.10 x 10^3 m, 1.100 x 10^3 m, etc.
These all have different significances. The figure 1100 m can't tell
you how many significance figures are involved without further information.

In particular, the example he gave involved changing significance
depending on the number of zeroes _before_ the other digits, not after
them, which is now how significance works. So obviously when he says
"significant digits" he doesn't mean the same thing that's used by
scientists, so the question can't really be answered.

If he simply wanted to get the number of digits involved, then that's
fine, but that's not what significance is.

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
Eternity is very long, especially near the end.
-- Woody Allen
Jul 19 '05 #23
Fredrik Lundh wrote:
"mrstephengross" wrote:
But, assuming you have your numbers as strings, I would suggest

looking
at str.split() and len().

Well, the numbers are in fact stored as numbers, so string processing won't work.


if they're not strings, your question is meaningless. as others have
pointed out, the exact internal representation for 0.103 is more like
0.102999999999999994337862574411701643839478492736 81640625
which has a lot more than 3 digits...


Actually, it's more like

0 01111111011 10100101111000110101001111110111110011101101100100 01

Jul 19 '05 #24
On Thu, 05 May 2005 20:08:46 -0700, Erik Max Francis wrote:
Grant's point was that as significance is used in scientific studies,
there's no way to answer the question without having the number in
advance.


My point was that the original poster never defined "significance" in that
manner, and in the manner in which he seemed to be using the term, my
comments made sense. Which is why the first thing I said was he needs to
rigorously define what he means, and everything after that was predicated
on the assumption he seemed to be looking at consumed screen space.
Jul 19 '05 #25
On 5 May 2005 11:13:46 -0700, "mrstephengross"
<mr************@hotmail.com> declaimed the following in
comp.lang.python:

The above code may produce "1.004", or "1.0040", or "1.00400",
depending on the stream's precision setting. I need a way to detect the
number of digits to the right of decimal point *prior* to doing any
kind of string conversion.
There isn't any method (except maybe in Ada using "fixed" not
"float" data types).

Consider (using decimal as I don't want to compute the binary
equivalents)...

10.04
1.004

are handled internally as

1.004 E1
1.004 E0

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Jul 19 '05 #26
Jeremy Bowers wrote:
A step which will require him to tell the printing routine how many digits
he wants printed.
Not necessarily; consider the str() of a float in Python, especially given
the "significant digits" aspect (it may be ill-defined, but I can think of
several well-defined ways to mean that, where str() embodies one of them).
The easiest way to tell how long the number will be when str prints it out
is to simply ask it.


and what language is str() implemented in?
In C++, this may be harder, as your output software may insist on
rendering everything directly, with no way to reach in and tell what it
did. Imagine the standard IOStreams, without the ability to stream into a
string.


but you can stream into a string buffer, and you can use sprintf() from C++,
so what's your point, besides stating that "if things were harder, they would
be harder"?

</F>

Jul 19 '05 #27
"mrstephengross" <mr************@hotmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Hi all... How can I find out the number of significant digits (to the
right of the decimal place, that is) in a double? At least, I *think*
that's what I'm asking for. For instance:

0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7

Thanks in advance!
--Steve (mr************@hotmail.com)
As a lot of the responders have pointed out, it's effectively
impossible to do so in any meaningful fashion if all you
have is the binary representation of the number.

One way of doing it is the ScientificDouble class in
PyFit (and in all other versions of FIT, for that matter.)
That provides a class that saves the original string
representation so it can be used to determine precision
for compares. It's a niche approach: it works well for
FIT's purposes, but it's not a general purpose method
of estimating precision throughout a lengthy calculation.
That requires quite different techniques.

See:

fit.c2.com
www.fitnesse.org
FitNesse Yahoo mailing list (see the files section for PyFit.)

John Roth


Jul 19 '05 #28
On Fri, 06 May 2005 08:27:03 +0200, Fredrik Lundh wrote:
Jeremy Bowers wrote:
> A step which will require him to tell the printing routine how many
> digits he wants printed.


Not necessarily; consider the str() of a float in Python, especially
given the "significant digits" aspect (it may be ill-defined, but I can
think of several well-defined ways to mean that, where str() embodies
one of them). The easiest way to tell how long the number will be when
str prints it out is to simply ask it.


and what language is str() implemented in?


Who cares? It demonstrates the existence of a print routine that prints a
variable number of characters.
In C++, this may be harder, as your output software may insist on
rendering everything directly, with no way to reach in and tell what it
did. Imagine the standard IOStreams, without the ability to stream into
a string.


but you can stream into a string buffer, and you can use sprintf() from
C++, so what's your point, besides stating that "if things were harder,
they would be harder"?


Giving the original poster the benefit of the doubt, I assumed he was
dealing with some sort of screen library that would render something
without telling him the size, that didn't use streams at all. If that
library also implemented its own pretty print, string streams and
everything else don't help; you need *that* library's pretty print.
Jul 19 '05 #29
James Stroud wrote:
Significant digits are an accounting concept. As such, it is up to the accountant to keep track of these as only she knows the precision of her measurements.

Koan for the day: What are the significant digits of 0.1? Hint:
`0.1`
James On Thursday 05 May 2005 10:37 am, so sayeth mrstephengross:
Hi all... How can I find out the number of significant digits (to

the right of the decimal place, that is) in a double? At least, I *think* that's what I'm asking for. For instance: 0.103 --> 3
0.0103 --> 4
0.00103 --> 5
0.000103 --> 6
0.0000103 --> 7


Since "significant digits" is a representation concept rather
than a mathematical one I'd be inclined to convert the value
to a string, split on the decimal point and return the length
of that.

A naive approach:

def sigdigits(x):
return len( ("%s" % float(x)).split('.')[1])
... but this gives bogus results for integers (saying that they
have "one" significant digit when, by your definition they have
zero.

I suppose you have to amend your definition to handle numbers
larger than 1 and I have to do something different than just
coercing into a float().

def sigdigits(x):
assert float(x) == x # raise an exception if we can't float it
ret = 0
strep = float(x)
(whole, fraction) = strep.split('.')
if int(fraction) > 0:
ret += len(fraction)
if int(whole) > 0:
ret += len(whole)

... I think that should do it. We could explicitly trim leading zeros
from the whole number part and trailing zeros from the fractional
part.
However I think the string representation (in Python's built-ins)
guarantees us that there will be no leading or trailing zeros unless
the part we're looking at is numerically equivalent to zero.

JimD

Jul 19 '05 #30

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by hana1 | last post: by
5 posts views Thread by DAVID SCHULMAN | last post: by
3 posts views Thread by mlafarlett | last post: by
6 posts views Thread by R.Biloti | last post: by
60 posts views Thread by Erick-> | last post: by
116 posts views Thread by Dilip | last post: by
7 posts views Thread by Michael Howes | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.