Long Numbers as a Character String

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 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

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



Leave a reply



Submit