monkeyUser
monkeyUser

Reputation: 4679

Subtract big number in bash

I Want to do a sub with two big number

my purpose is

1805334111369276485744644020321551471447190030955050085289-3369574570478873127315415525946742317481702644901195284480

I try with

echo $((1805334111369276485744644020321551471447190030955050085289-3369574570478873127315415525946742317481702644901195284480))

My result is: 3160661815551241129

but it's not correct.

I can do the similar operation in console chrome and I Have

-1.5642404591095965e+

How can I do this operation in bash? I tried even with expr, but without lucky

It's ok to check if a number is greater then another

in shell

echo $((1805334111369276485744644020321551471447190030955050085289>3369574570478873127315415525946742317481702644901195284480))

result: 1

same operation in chrome

1805334111369276485744644020321551471447190030955050085289>3369574570478873127315415525946742317481702644901195284480

result:false

And chrome is right

Upvotes: 3

Views: 759

Answers (4)

Aaron
Aaron

Reputation: 24812

The ARITHMETIC EVALUATION section of bash's manual explains why you get this result with $((...)) :

Evaluation is done in fixed-width integers with no check for overflow

You may be able to use expr (depending on compile-time options, check @Benjamin W's comment), but you need spaces between the operator and its operands :

$ expr 1805334111369276485744644020321551471447190030955050085289 - 3369574570478873127315415525946742317481702644901195284480
-1564240459109596641570771505625190846034512613946145199191

As @PesaThe mentions you can also use bc, one of its main features being able to handle arbitrary precision arithmetics :

bc <<< "1805334111369276485744644020321551471447190030955050085289 - 3369574570478873127315415525946742317481702644901195284480"
-1564240459109596641570771505625190846034512613946145199191

Upvotes: 4

anubhava
anubhava

Reputation: 785481

Mac OSX awk can also handle big numbers:

awk 'BEGIN{print 1805334111369276485744644020321551471447190030955050085289 - \
3369574570478873127315415525946742317481702644901195284480}'

-1.56424045910959651912822682029e+57

Or by using printf:

awk 'BEGIN{printf "%.5e\n", 1805334111369276485744644020321551471447190030955050085289 - \
3369574570478873127315415525946742317481702644901195284480}'

-1.56424e+57

On the other hand GNU awk needs -M switch to support big numbers so use:

gawk -M 'BEGIN{print 1805334111369276485744644020321551471447190030955050085289 - \
3369574570478873127315415525946742317481702644901195284480}'

Upvotes: 1

gniourf_gniourf
gniourf_gniourf

Reputation: 46853

If you're feeling adventurous you can use that good old dc (desk calculator, a cute RPN calculator):

dc <<< "1805334111369276485744644020321551471447190030955050085289 3369574570478873127315415525946742317481702644901195284480 - p"

Answer is: -1564240459109596641570771505625190846034512613946145199191

Upvotes: 1

stack0114106
stack0114106

Reputation: 8711

You can use Perl

$ perl -le ' BEGIN { use Math::BigInt; my $x=Math::BigInt->new("1805334111369276485744644020321551471447190030955050085289"); my $y=Math::BigInt->new("3369574570478873127315415525946742317481702644901195284480"); print $x->bsub($y) } '
-1564240459109596641570771505625190846034512613946145199191
$ perl -le ' BEGIN { use Math::BigInt; my $x=Math::BigInt->new("1805334111369276485744644020321551471447190030955050085289"); my $y=Math::BigInt->new("3369574570478873127315415525946742317481702644901195284480"); printf("%g\n",$x->bsub($y)) } '
-1.56424e+57
$

If you want to pass echo output to Perl, then

$ echo "1805334111369276485744644020321551471447190030955050085289-3369574570478873127315415525946742317481702644901195284480" | perl -ne ' BEGIN { use Math::BigInt } /(\d+)-(\d+)/; $x=Math::BigInt->new($1); $y=Math::BigInt->new($2); printf("%g\n",$x->bsub($y)) '
-1.56424e+57
$

As @PesaThe mentioned you can use bc also

$ bc <<< "1805334111369276485744644020321551471447190030955050085289-3369574570478873127315415525946742317481702644901195284480"
-1564240459109596641570771505625190846034512613946145199191
$

Upvotes: 1

Related Questions