Long Numbers As A Character String
You can specify colClasses on your fread or read.csv statement.
bignums
429382748394831049284934
429382748394831049284935
429382748394831049284936
429382748394831049284937
429382748394831049284938
429382748394831049284939
bignums <- read.csv("~/Desktop/bignums.txt", sep="", colClasses = 'character')
Making sure a string repr of decimal number is always n characters long
One can make use of BigDecimal
, and for the integer part BigInteger
.
/**
* @param num number representation.
* @param max the maximal length the result should have.
* @return
*/
public static String truncateNumber(String num, int max) {
num = num.replaceFirst("\\.0*$", "");
BigDecimal x = new BigDecimal(num);
// Large numbers - integral part
String bigI = x.toBigInteger().toString();
if (bigI.length() > max) {
int expon10 = bigI.length() - max - 1; // - 1 for E
// Digits after E:
if (expon10 == 0) {
++expon10;
} else {
for (int p = expon10; p > 0; ++p) {
++expon10;
p /= 10;
}
}
x = x.movePointLeft(expon10);
String plain = x.toPlainString().substring(0, max - 1 - expon10);
return plain + "E" + expon10;
}
// Tiny numbers - 0.000 (as E-1 already requires 3 positions)
String reprP = x.toPlainString();
if (reprP.startsWith("-0.00")) {
return truncateNumber(num.substring(1), max - 1);
} else if (reprP.startsWith("0.00")) {
String reprE = x.toEngineeringString(); // Does most work.
int epos = reprE.indexOf('E');
String mantissa = reprE.substring(0, epos);
String exp = reprE.substring(epos);
return mantissa.substring(0, Math.min(epos, max - exp.length())) + exp;
}
// Normal range - assumed in format 123.456, integral part in range
String simple = x.toPlainString();
if (simple.length() > max) {
simple = simple.substring(0, max).replaceFirst("\\.0*$", "");
}
return simple;
}
That can probably written more nicely, substrings ending on \.0*
, especially there is some repetitive usage of toPlainString and such. Also a too smal max
will be harmful.
Whether num
maybe given in scientific / engineering notation is also open.
Javascript - get very big number as string containing all digits
You could use toLocaleString
method (with some options, if needed):
const s = Number.MAX_VALUE.toLocaleString(undefined, {
style: 'decimal',
useGrouping: false //Flip to true if you want to include commas
});
console.log(s)
R: How to convert long number to string to save precision
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 and5L
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 thisnumeric
to the function, but by this point the precision has already been lost. Ergo the otherwise-illogicalbit64::as.integer64(-8664354335142704128) == bit64::as.integer64(-8664354335142703762)
# [1] TRUEIn 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] -8664254335142703104It 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 ainteger64
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.NULLSo,
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] FALSEFYI, 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
Formatting long numbers as strings
I don't think there's a built-in function that does that. You'll have to roll your own, e.g.:
def human_format(num):
magnitude = 0
while abs(num) >= 1000:
magnitude += 1
num /= 1000.0
# add more suffixes if you need them
return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])
print('the answer is %s' % human_format(7436313)) # prints 'the answer is 7.44M'
How to convert a character string (which is beyond long long int's range) to integer value
one of the way to handle such large numbers is to use integer array. such as
int a[200]
and perform operations on the array as you perform operations on numbers using basic arithmetic of considering each digit of a number i.e for example consider multiplying 2 numbers 1234*4567 what you do is, store 1234 in a[] and 4567 in b[]. use a temporary array c[] then,
4*7=28 so next
3*7+2(which can be computed as (int)28/10)=23
2*7+2=16
1*7+1=8
so you get 8638 in first iteration store it in c[] then, do the same using 6 i.e 1234*6 and do
8638+1234*6*10
i think now you got this basic maths. use this type basic maths method to perform operations on large numbers stored in array. all operation can be implemented by using such digit level operations.
Convert long number into abbreviated string in JavaScript, with a special shortness requirement
I believe ninjagecko's solution doesn't quite conform with the standard you wanted. The following function does:
function intToString (value) {
var suffixes = ["", "k", "m", "b","t"];
var suffixNum = Math.floor((""+value).length/3);
var shortValue = parseFloat((suffixNum != 0 ? (value / Math.pow(1000,suffixNum)) : value).toPrecision(2));
if (shortValue % 1 != 0) {
shortValue = shortValue.toFixed(1);
}
return shortValue+suffixes[suffixNum];
}
For values greater than 99 trillion no letter will be added, which can be easily fixed by appending to the 'suffixes' array.
Edit by Philipp follows: With the following changes it fits with all requirements perfectly!
function abbreviateNumber(value) {
var newValue = value;
if (value >= 1000) {
var suffixes = ["", "k", "m", "b","t"];
var suffixNum = Math.floor( (""+value).length/3 );
var shortValue = '';
for (var precision = 2; precision >= 1; precision--) {
shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
if (dotLessShortValue.length <= 2) { break; }
}
if (shortValue % 1 != 0) shortValue = shortValue.toFixed(1);
newValue = shortValue+suffixes[suffixNum];
}
return newValue;
}
Related Topics
Create Frequency Tables for Multiple Factor Columns in R
Set Margin Size When Converting from Markdown to PDF with Pandoc
Merge Data Frames Based on Rownames in R
Mean of a Column in a Data Frame, Given the Column's Name
Ggplot Centered Names on a Map
How to Change Order of Boxplots When Using Ggplot2
How to Position Strip Labels in Facet_Wrap Like in Facet_Grid
Making a Stacked Area Plot Using Ggplot2
Split Dataframe by Levels of a Factor and Name Dataframes by Those Levels
What's the Difference Between Lapply and Do.Call
Compile R Script into Standalone .Exe File
Conditionally Display a Block of Text in R Markdown
How to Edit and Debug R Library Sources
Wide to Long Multiple Measures Each Time
Changing the Line Type in the Ggplot Legend
Filling Area Under Curve Based on Value