Skip to content
Prev 299387 / 398503 Next

number of decimal places in a number?

I had thought of also (as well as my numerical routing) suggesting
a "gsub()" type solution like Joshua's below, but held back because
the result could depend on how the number arose (keyboard input,
file input, or from computation within R).

However, I now also realise that (again because of binary rounding
errors), the "gsub()" method has interesting differences from my
numerical method. Example:

[A] (as from my original method):
  f(123456789.123456789)
  # [1] 7

[B] (the "gsub()" method)
  nchar(gsub("(.*\\.)|([0]*$)", "", as.character(123456789.123456789)))
  # [1] 6

Now look at:

[C] (what as.character() does to 123456789.123456789)
  as.character(123456789.123456789)
  # [1] "123456789.123457"

[D] ("22" is the maximum number of decimal digits for print())
  print(123456789.123456789,22)
  # [1] 123456789.1234568

So as.character() has rounded it to 6 decimal places (agreeing
with [B]), while using print() with the maximum of 22 digits
(more than enough for the 18 digits in 123456789.123456789)
rounds it to 7 decimal places (i.e. 16 digits in all), which
is about the limit (depending on the magnitude of the number)
that R can hold internally; this agrees with [A].

Note the difference between

[D] ("22" is the maximum number of decimal digits for print())
  print(123456789.123456789,22)
  # [1] 123456789.1234568

[E] (similar, but with a different magnitude)
  print(923456789.123456789,22)
  # [1] 923456789.123457

(compare with [C]).

So, clearly, there is potential uncertainty in the ouput
from either method, but perhaps there is somewhat more
uncertainty with the "gsub()" method.

Also, another nasty little trap with "gsub()":

[F] (my method)
  f(0.0000012345)
  # [1] 10

[G] ("gsub()" method)
  nchar(gsub("(.*\\.)|([0]*$)", "", as.character(0.0000012345)))
  # [1] 8

which arises because:

  as.character(0.0000012345)
  # [1] "1.2345e-06"

There would seem to be no clean general solution to this
question. An important issue would be: What use do you
want to put the result to?

If there is something in the logic of your application
which depends critically on the numbers of decimal places
in its numerical input, then the final result could be
completey wrong because of these uncertainties.

In such a case, it might be best to force initial input
to be of character format. For example, if reading numerical
data into a dataframe from (say) a CSV file, then the option

Data <- read.csv("datafile.csv",colClasses="character")

(or similar) would convert all numerical data into the equivalent
character formats. Then Joshua's "gsub()" method would always
give exactly the right result when applied to these character
strings. Then, having got that out of the way, you can convert
the character strings into numeric (to within the precision
that R will allow).

However, if something in the logic depends critically on the
numbers of "decimal places" in numbers computed internally by R,
then I think the case is hopeless!

Ted.
On 07-Jul-2012 10:44:55 Joshua Wiley wrote:
-------------------------------------------------
E-Mail: (Ted Harding) <Ted.Harding at wlandres.net>
Date: 07-Jul-2012  Time: 13:12:31
This message was sent by XFMail