I need a R function that always returns same number of digits after the decimal point regardless of how big the argument is. I tried round() but it does not work this way. Here is my example:
Rweb:> round(111234.678912,4) # expect 111234.6789
[1] 111234.7
Rweb:> round(111234.678912/10,4) # expect 11123.4679
[1] 11123.47
Rweb:> round(111234.678912/100,4) # expect 1112.3468
[1] 1112.347
Rweb:> round(111234.678912/1000,4)
[1] 111.2347
Rweb:> round(111234.678912/10000,4)
[1] 11.1235
It does work if the argument is in exponential format but I need work with numbers in floating format.
It does round the number to the correct number of digits. However, R has limits on the number of digits it displays of very large numbers. That is- those digits are there, they just aren't shown.
You can see this like so:
> round(111234.678912,4)
[1] 111234.7
> round(111234.678912,4) - 111234
[1] 0.6789
You can use formatC to display it with any desired number of digits:
> n = round(111234.678912,4)
> formatC(n, format="f")
[1] "111234.6789"
> formatC(n, format="f", digits=2)
[1] "111234.68"
As #mnel helpfully points out, you can also set the number of digits shown (including those to the left of the decimal point) using options:
> options(digits=6)
> round(111234.678912,4)
[1] 111235
> options(digits=10)
> round(111234.678912,4)
[1] 111234.6789
For anyone else who, like me, thought the question was going to be about bignums :-), there's this to ponder :-)
Rgames> bfoo<-mpfr("1.234545678909887665453421")
Rgames> bfoo
1 'mpfr' number of precision 84 bits
[1] 1.234545678909887665453421
Rgames> round(bfoo,10)
1 'mpfr' number of precision 84 bits
[1] 1.23454567889999999999999999`
let x is a number with big decimal places.
x<-1111111234.6547389758965789345
Here x is a number with big decimal places , you can format decimal places
as your wish.
Such that we wish to take up to 8 decimal places of this number.
x<-c(1111111234.6547389758965789345)
y<-formatC(x,digits=8,format="f")
[1] "1111111234.65473890"
Here format="f" gives number in the usual decimal places say, xxx.xxx.
But if you wanted to get a integer number from this object x you use
format="d"
About "bignums", #Carl Witthoft:
Thanks, Carl. ... I did think about bignums, when I read it. Are you sure there
's a problem with the rounding?
See this:
> mpfr("1.2345456789", prec=84)
1 'mpfr' number of precision 84 bits
[1] 1.23454567889999999999999999
and note that Rmpfr (I'm the maintainer) does stay close to the underlying MPFR library. For round(), I've applied the logic/principle of f(x) returning a result with the same formal precision as x. If you want rounding with decreased formal precision, you can conveniently use roundMpfr():
> roundMpfr(bfoo, 32)
1 'mpfr' number of precision 32 bits
[1] 1.2345456788
Related
I am wondering if converting numerics to characters and then back again in R can ever change the number? For example, does as.character round off numerics after a certain amount of decimal places (if so, how many)?
#jogo thanks for the suggestion :)
Here is the comment as an answer:
From ?as.character():
as.character represents real and complex numbers to 15 significant
digits (technically the compiler's setting of the ISO C constant
DBL_DIG, which will be 15 on machines supporting IEC60559 arithmetic
according to the C99 standard). This ensures that all the digits in
the result will be reliable (and not the result of representation
error), but does mean that conversion to character and back to numeric
may change the number. If you want to convert numbers to character
with the maximum possible precision, use format.
So yes it does change the number if you have more than 15 significant digits. See:
> as.character(1.000000000000001) # more than 15 significant digits
[1] "1"
> as.character(1.00000000000001) # less than 15 significant digits
[1] "1.00000000000001"
Here are some other examples:
y <- as.numeric(as.character(pi))
identical(y, pi) ### gives FALSE
or
x <- 1/7
y <- as.numeric(as.character(x))
x-y
or
as.numeric(as.character(.Machine$double.xmax)) ## result: Inf
I have a problem to convert a long number to a string in R. How to easily convert a number to string to preserve precision? A have a simple example below.
a = -8664354335142704128
toString(a)
[1] "-8664354335142704128"
b = -8664354335142703762
toString(b)
[1] "-8664354335142704128"
a == b
[1] TRUE
I expected toString(a) == toString(b), but I got different values. I suppose toString() converts the number to float or something like that before converting to string.
Thank you for your help.
Edit:
> -8664354335142704128 == -8664354335142703762
[1] TRUE
> along = bit64::as.integer64(-8664354335142704128)
> blong = bit64::as.integer64(-8664354335142703762)
> along == blong
[1] TRUE
> blong
integer64
[1] -8664354335142704128
I also tried:
> as.character(blong)
[1] "-8664354335142704128"
> sprintf("%f", -8664354335142703762)
[1] "-8664354335142704128.000000"
> sprintf("%f", blong)
[1] "-0.000000"
Edit 2:
My question first was, if I can convert a long number to string without loss. Then I realized, in R is impossible to get the real value of a long number passed into a function, because R automatically read the value with the loss.
For example, I have the function:
> my_function <- function(long_number){
+ string_number <- toString(long_number)
+ print(string_number)
+ }
If someone used it and passed a long number, I am not able to get the information, which number was passed exactly.
> my_function(-8664354335142703762)
[1] "-8664354335142704128"
For example, if I read some numbers from a file, it is easy. But it is not my case. I just need to use something that some user passed.
I am not R expert, so I just was curious why in another language it works and in R not. For example in Python:
>>> def my_function(long_number):
... string_number = str(long_number)
... print(string_number)
...
>>> my_function(-8664354335142703762)
-8664354335142703762
Now I know, the problem is how R reads and stores numbers. Every language can do it differently. I have to change the way how to pass numbers to R function, and it solves my problem.
So the correct answer to my question is:
""I suppose toString() converts the number to float", nope, you did it yourself (even if unintentionally)." - Nope, R did it itself, that is the way how R reads numbers.
So I marked r2evans answer as the best answer because this user helped me to find the right solution. Thank you!
Bottom line up front, you must (in this case) read in your large numbers as string before converting to 64-bit integers:
bit64::as.integer64("-8664354335142704128") == bit64::as.integer64("-8664354335142703762")
# [1] FALSE
Some points about what you've tried:
"I suppose toString() converts the number to float", nope, you did it yourself (even if unintentionally). In R, when creating a number, 5 is a float and 5L is an integer. Even if you had tried to create it as an integer, it would have complained and lost precision anyway:
class(5)
# [1] "numeric"
class(5L)
# [1] "integer"
class(-8664354335142703762)
# [1] "numeric"
class(-8664354335142703762L)
# Warning: non-integer value 8664354335142703762L qualified with L; using numeric value
# [1] "numeric"
more appropriately, when you type it in as a number and then try to convert it, R processes the inside of the parentheses first. That is, with
bit64::as.integer64(-8664354335142704128)
R first has to parse and "understand" everything inside the parentheses before it can be passed to the function. (This is typically a compiler/language-parsing thing, not just an R thing.) In this case, it sees that it appears to be a (large) negative float, so it creates a class numeric (float). Only then does it send this numeric to the function, but by this point the precision has already been lost. Ergo the otherwise-illogical
bit64::as.integer64(-8664354335142704128) == bit64::as.integer64(-8664354335142703762)
# [1] TRUE
In this case, it just *happens that the 64-bit version of that number is equal to what you intended.
bit64::as.integer64(-8664254335142704128) # ends in 4128
# integer64
# [1] -8664254335142704128 # ends in 4128, yay! (coincidence?)
If you subtract one, it results in the same effective integer64:
bit64::as.integer64(-8664354335142704127) # ends in 4127
# integer64
# [1] -8664354335142704128 # ends in 4128 ?
This continues for quite a while, until it finally shifts to the next rounding point
bit64::as.integer64(-8664254335142703617)
# integer64
# [1] -8664254335142704128
bit64::as.integer64(-8664254335142703616)
# integer64
# [1] -8664254335142703104
It is unlikely to be coincidence that the difference is 1024, or 2^10. I haven't fished yet, but I'm guessing there's something meaningful about this with respect to floating point precision in 32-bit land.
fortunately, bit64::as.integer64 has several S3 methods, useful for converting different formats/classes to a integer64
library(bit64)
methods(as.integer64)
# [1] as.integer64.character as.integer64.double as.integer64.factor
# [4] as.integer64.integer as.integer64.integer64 as.integer64.logical
# [7] as.integer64.NULL
So, bit64::as.integer64.character can be useful, since precision is not lost when you type it or read it in as a string:
bit64::as.integer64("-8664354335142704128")
# integer64
# [1] -8664354335142704128
bit64::as.integer64("-8664354335142704128") == bit64::as.integer64("-8664354335142703762")
# [1] FALSE
FYI, your number is already near the 64-bit boundary:
-.Machine$integer.max
# [1] -2147483647
-(2^31-1)
# [1] -2147483647
log(8664354335142704128, 2)
# [1] 62.9098
-2^63 # the approximate +/- range of 64-bit integers
# [1] -9.223372e+18
-8664354335142704128
# [1] -8.664354e+18
I have a determinant which I know is a square of an integer, but because its value is bigger than .Machine$integer.max I used the mpfr package.
But I still have problems.
Here is the algorithm:
> a<- mpfr(sqrt(det(M)), precBits=512);a
1 'mpfr' number of precision 512 bits
[1] 430080000000001.1875
Could you please help me?
Is performance an issue? If not, then the following should work.
> x<-mpfr(31415926535897932384626433832795, 500)
> is.whole(sqrt(x))
[1] FALSE
> y<-mpfr(31415926535897932384626433832794, 500)^2
> y
1 'mpfr' number of precision 500 bits
[1] 986960440108935918772069008410384076085841574993068761741787136
> is.whole(sqrt(y))
[1] TRUE
I previously used the prod() function in R that can give me the product, and it works fine for big numbers. The numbers I have are too small like 1.294528e-07 and once I take the product it gives me a 0. How can I get the accurate product with exact decimal numbers?
This sounds like a job for Rmpfr:
x <- 1.294528e-07;
x^100;
## [1] 0
library('Rmpfr');
mpfr200 <- function(...) mpfr(...,precBits=200);
x <- mpfr200(1.294528e-07);
x^100;
## 1 'mpfr' number of precision 200 bits
## [1] 1.6260909947893069252110098843324246495136887016336218206204661e-689
Or you could try using big rationals from gmp, although that can get unwieldy fast:
library('gmp');
x <- as.bigq(1.294528e-07);
x^100;
## Big Rational ('bigq') :
## [1] 863201774730415899361077141424209396921125795515936990572548766128423810485376236957138978501283812494839104247698243918794530436552717763753923415271480284747830193402522833445368586578235815336302329397252055448087703163456038666698935354732741208048881276922439385153961853551463063865863458552423073323374618023089542368149617965922293453325011050815707644365808660423522776994133587512616070446174486428153909409377712433145387919387175172482342168167092570331925560436171324785600650158865676862026009729048525389272889703709380624434349438465164559591242984791355618727989751127260257309242805499481511142165616784856784942417419338154196561431152388897904866047119736434465720555151366859879507712533271194851766672024261634534292974370183919317337519761869292257947511511111895425764926171263133863980854536246390233199502174749146911367500644673909293464659053254182209374190247093969004854275674922622004129684228283369400286413197699863545912211106461047595912964876198783114172495242447965086668614473659343976994896679029656266765528726921384485164153780083326552118475505412074971594197272427677831237385443579950907872485700396062323506489811292749356021319775368577664875790645937426179486396681942844892307294288187671687510056569029216067321069225537944854772595983467728588640812585079820715315382504185719050646602130250650306723313760231069912835376365077115331890400516502810239814459239282321065702537572103441710647744406489548580900916084596895906189449738524638127337711843685456775272799845630310027842996833372802952394634016929280394482001/53084469288402965415857953902888840109250315594591772197851276288408082158869345776872184284291470495326835835491268017776297213098616208286592801322449982740570898437845767564651639451594841758957168240360072929342348878909784083488070009533176658698675760470010215436132534526706916446032842195249059760060209393388578176281027744679436285035293376786965957429093838689438026612141820062960073237944227430409290082873605748455349816343081466372681612738552636294666573661997989000563367893746123926316870120929629731301360766711677076606816082939449299471019533119911247114865751561110071173719092050562287666719013887097553109594042589835370732409680749273477741701995190365166750190649349508586781414000112900259875654673888811075100415790235930270448790550846107436360615795146817327563001398966815753145995110673462134196824939359497706430237425390060733252224220979131253874493851823165781457427314551881655553433521397260371393668335053627112038905459972042994824319713601980913921755210218082851146588240382210406887660412630451416112206306502796230074832738884324233514086958873577398927563897852887699678587467916741882087729456997268017154775450070371874680332524775280043635270781581135769020865808796073362505082201497885288236887117727248916243704472117062440908853938749830047482062530807255930310025959255017626077608884577821899189515192765061903944746945679900747890669013446056647522960607623949336195016784356934505954115977283306997415274187752372480232652878520163417566097389917356958213807994947634794209832173114356392822435844256992216702376456519427913660058510779720382422426729352627871147386069533497741201545766859622239986052843328404669795291152396764393702113455439610494964706121896827191760262984304690887475635610694078746800875955908479469409563047706020039725815572087005410536948676710051947334063697608908539017716795313119629533327813992071776512146390147185444968042597376280912548998385218672413833388480083312283356458666501168482077474943858309275329657545594008977132937574085616539588927255406484838471048801662983695044651588178399267847057683205128610922849562650411762874243138435345707386259866513245949164125352989897783775852403441398200260025840304184956928642989258546038224598392605412214974894309376
(Notice the slash at character 1570 into that digit sequence.)
Does R store the smallest possibly representable scientific value?
To clarify: on my current machine:
>1e-300
[1] 1e-300
While
>1e-400
[1] 0
Through trial and error I know it is somewhere around the e-324 mark on my machine (where it also starts losing precision).
>1e-324
[1] 0
>5e-324
[1] 4.940656e-324
I've searched through the .Machine list and none of the values it stores contain either the value, or the exponent I'm looking for.
Edit:
Linked threads on the side indicate that this should be .Machine$double.eps, which is 2.220446e-16. Clearly this is no longer the case?
The smallest normalised is double.xmin, as described in this page. The Wikipedia entry is very interesting and has the subnormal limit which is 2^-1074, which is approximately 4.9406564584124654 x 10^-324 (from Wikipedia as Ben Bolker mentioned in the comments). Your output in R is matching this value.
double.epsilon is not what you think. It is the smallest number you can add to 1 such as you obtain a number which will be not recognised as 1.
I suggest you read about how the double are stored in memory and the basics of double operations. Once you understand how a double is stored the lower limit is obvious.
The accepted answer remains correct for base R, but using the package Rmpfr enables arbitrary precision. Example:
First, note issue in base R:
> p <- c("5e-600","2e-324","3e-324","4e-324", "5e-324","6e-324","7.1e-324","8e-324")
> as.numeric(p)
[1] 0.000000e+00 0.000000e+00 4.940656e-324 4.940656e-324 4.940656e-324 4.940656e-324
[7] 4.940656e-324 9.881313e-324
Observe that as we near the limit the precision is an issue and all values are 4.940656e-324.
Now use mpfr function from 'Rmpfr` package to cast the strings as floats:
> library(Rmpfr)
> .N <- function(.) mpfr(., precBits = 20)
> .N(p)
8 'mpfr' numbers of precision 20 bits
[1] 5.0000007e-600 2.00000e-324 2.9999979e-324 4.00000e-324 4.9999966e-324 5.9999959e-324
[7] 7.09999e-324 8.00000e-324