>> -999999999
== -999999999
>> 999999999
== 999999999
If you digit a bigger number is automatically transformed in a decimal precision number. Decimal numbers has 15 digits of precision:
>> 12345678901234567890123456789
== 1.23456789012346E+28
This behavior is normal, it's difficult to preform calculus that need more than 15 digits. For example in engineering field no more than 3-4 digits is necessary.
However it can be useful working with big integers, like indexing of pages, databases, etc.
Rebol can manipulate any longer integer, if you need it; just transform the number in a string and use the following script:
rebol [
Author: [ "Alban Gabillon" "Massimiliano Vessi" ]
Library: [
level: 'intermediate
platform: 'all
type: tool
domain: [math]
tested-under: windows
support: none
license: none
see-also: none
]
History: [
[1.0 22-mar-2007 "First version"]
[2.1 29-11-2011 "Now it's more human usable"]
]
Title: "Bignumbers.r"
File: %bignumbers.r
Owner: "Alban Gabillon"
Version: 2.1.0
Date: 22-Mar-2007
Purpose: {
This script allows you to apply the four classical operations (big-add, big-subtract, big-divide, big-multiply) on very big positive integers.
Size of the integers is only limited by the size of a rebol string since numbers are represented as strings. }]
big-add: func [
{add two big numbers }
n1 [string!]
n2 [string!]
/local mem plus n result][
n1: reverse copy n1
n2: reverse copy n2
mem: 0
result: copy ""
if (length? n1) < (length? n2) [n: n1 n1: n2 n2: n]
while [not tail? n2][
plus: to-string ((to-integer to-string n1/1) + (to-integer to-string n2/1) + mem)
either (length? plus) = 1 [mem: 0 result: insert result plus/1][mem: 1 result: insert result plus/2]
n1: next n1
n2: next n2
]
while [ not tail? n1][
plus: to-string ((to-integer to-string n1/1) + mem)
either (length? plus) = 1 [mem: 0 result: insert result plus/1][mem: 1 result: insert result plus/2]
n1: next n1
]
either mem = 1 [insert result #"1"][insert result copy n1]
result: head result
return result
]
big-multiply: func ["multiply two big numbers" n1 [string!] n2 [string!] /local temp ] [
n1: reverse copy n1
n2: copy n2
temp: copy "0"
foreach item n1 [
for i 1 (to-integer to-string item) 1 [
temp: big-add temp n2
]
append n2 "0"
]
return temp
]
big-greater: func [
{compare two bignumbers:
return true if n1 > n2
return false if n1 < n2
return none if n1 = n2
}
n1 [string!]
n2 [string!]][
n1: reverse copy n1
n2: reverse copy n2
either (length? n1) <> (length? n2) [(length? n1) > (length? n2)][
either equal? n1 n2 [none][
n1: back tail n1
n2: back tail n2
while [n1/1 = n2/1][n1: back n1 n2: back n2]
n1/1 > n2/1
]
]
]
big-sub: func [
{substract the smallest big number from the largest one }
n1 [string!]
n2 [string!]
/local mem minus n result][
if big-greater n2 n1 [n: n1 n1: n2 n2: n]
n1: reverse copy n1
n2: reverse copy n2
mem: 0
result: copy ""
while [not tail? n2][
minus: to-string (((to-integer to-string n1/1) - mem) + (10 - (to-integer to-string n2/1)))
either (length? minus) = 1 [mem: 1 result: insert result minus/1][mem: 0 result: insert result minus/2]
n1: next n1
n2: next n2
]
while [all[mem = 1 not tail? n1]][
minus: to-string ((to-integer to-string n1/1) + (10 - mem))
either (length? minus) = 1 [mem: 1 result: insert result minus/1][mem: 0 result: insert result minus/2]
n1: next n1
]
insert result copy n1
result: back tail result
while [all [result/1 = #"0" not head? result]][result: back result]
clear next result
result: head result
return reverse result
]
big-divide: func [
{divide two big numbers -
output is a block of two numbers [quotient remainder]}
n1 [string!]
n2 [string!]
/local count ][
n1: copy n1 ;this avoid to modify the original block
if big-greater n2 n1 [return reduce ["0" n1]] ;obvius
if equal? n1 n2 [return reduce ["1" "0"]] ;obvius
count: "0"
while [big-greater n1 n2 ] [
n1: big-sub n1 n2
count: big-add count "1"
]
if equal? n1 n2 [
count: big-add count "1"
n1: "0"
]
return reduce [count n1]
]
It can be used this way (now I'll use small number as example):
>> big-add "253" "2"
== "255"
>> big-sub "253" "2"
== "251"
>> big-multiply "253" "2"
== "506"
>> big-divide "253" "2"
== ["126" "1"]
Real world examples:
>> big-add "123456789012345678901234567890" "123456789012345678901234567890"
== "246913578024691357802469135780"
>> big-sub "123456789012345678901234567890" "123456789012345678901234567890"
== "0"
>> big-multiply "123456789012345678901234567890" "123456789012345678901234567890"
== {15241578753238836750495351562536198787501905199875019052100}
>> big-divide "123456789012345678901234567890" "123456789012345678901234567890"
== ["1" "0"]
No comments:
Post a Comment