Generalised floating point addition: Difference between revisions

m
m (→‎{{header|Phix}}: added syntax colouring the hard way)
m (→‎{{header|Wren}}: Minor tidy)
 
(One intermediate revision by one other user not shown)
Line 40:
'''See also:''' [[Generalised floating point multiplication#ALGOL 68|Generalised floating point multiplication]]
 
'''File: Template.Big_float.Addition.a68''' - task code<langsyntaxhighlight lang="algol68">########################################
# Define the basic addition operators #
# for the generalised base #
Line 136:
out # EXIT #
FI
);</langsyntaxhighlight>'''File: Template.Big_float.Base.a68''' - task utility code<langsyntaxhighlight lang="algol68"># -*- coding: utf-8 -*- #
################################################
# Define the basic operators and routines for #
Line 246:
# re anchor the array with a shift #
OP SHL = (DIGITS in, INT shl)DIGITS: in[@MSD in-shl];
OP SHR = (DIGITS in, INT shr)DIGITS: in[@MSD in+shr];</langsyntaxhighlight>'''File: Template.Big_float_BCD.Base.a68 - test case code'''<langsyntaxhighlight lang="algol68">################################################
# Define the basic operators and routines for #
# manipulating DIGITS specific to a BCD base #
Line 420:
out
FI
);</langsyntaxhighlight>'''File: Template.Big_float.Subtraction.a68''' - bonus subtraction definitions<langsyntaxhighlight lang="algol68">OP - = (DIGITS arg)DIGITS: (
DIGITS out := arg;
FOR digit FROM LSD arg BY digit order OF arithmetic TO MSD arg DO
Line 446:
OP - = (DIGITS a, DIGIT b)DIGITS: a - INITDIGITS b;
OP - = (DIGIT a, DIGITS b)DIGITS: INITDIGITS a - a;
OP -:= = (REF DIGITS lhs, DIGIT arg)DIGITS: lhs := lhs - arg;</langsyntaxhighlight>'''File: test.Big_float_BCD.Addition.a68''' - test case code main program<langsyntaxhighlight lang="algol68">#!/usr/local/bin/a68g --script #
 
##################################################################
Line 496:
printf(($g$, REPR total, $" => "b("Passed","Failed")"!"$, LSD total = MSD total, $l$))
OD
)</langsyntaxhighlight>'''Output:'''
<pre style="height:15ex;overflow:scroll">
12345679e63 x 81 gives: 999999999e63, Plus 1e63 gives: 1e72 => Passed!
Line 532:
=={{header|Go}}==
Although the big.Float type already has a 'Mul' method, we re-implement it by repeated application of the 'Add' method.
<langsyntaxhighlight lang="go">package main
 
import (
Line 564:
e -= 9
}
}</langsyntaxhighlight>
 
{{out}}
Line 607:
Given
 
<langsyntaxhighlight lang="j">e=: 2 : 0
u * 10x ^ v
)</langsyntaxhighlight>
 
In other words, given a parse time word (<code>e</code>) which combines its two arguments as numbers, multiplying the number on its left by the exact exponent of 10 given on the right, I can do:
 
<syntaxhighlight lang="text"> 1 e 63 + 12345679 e 63 * 81
1000000000000000000000000000000000000000000000000000000000000000000000000
1 e 54 + 12345679012345679 e 54 * 81
Line 620:
1000000000000000000000000000000000000000000000000000000000000000000000000
1 e 36 + 12345679012345679012345679012345679x e 36 * 81
1000000000000000000000000000000000000000000000000000000000000000000000000</langsyntaxhighlight>
 
As usual, if the results seem mysterious, it can be helpful to examine intermediate results. For example:
 
<syntaxhighlight lang="text"> 1 e 36 ,: 12345679012345679012345679012345679x e 36 * 81
1000000000000000000000000000000000000
999999999999999999999999999999999999000000000000000000000000000000000000</langsyntaxhighlight>
 
So, ok, let's turn this into a sequence:
 
<langsyntaxhighlight lang="j">factor=: [: +/ [: 12345679 e ] _9 * 1 + i.&.(+&8)
adjust=: 1 e (_9&*)</langsyntaxhighlight>
 
Here we show some examples of what these words mean:
 
<langsyntaxhighlight lang="j"> factor _4 NB. this is the number we multiply by 81
12345679012345679012345679012345679000000000000000000000000000000000000
factor _3
Line 646:
1000000000000000000000000000000000000
adjust _3
1000000000000000000000000000</langsyntaxhighlight>
 
Given these words:
 
<syntaxhighlight lang="j">
<lang j>
_7+i.29 NB. these are the sequence elements we are going to generate
_7 _6 _5 _4 _3 _2 _1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Line 656:
29
~.(adju + 81 * factor)&> _7+i.29 NB. here we see that they are all the same number
1000000000000000000000000000000000000000000000000000000000000000000000000</langsyntaxhighlight>
 
Note that <code>~. list</code> returns the unique elements from that list.
Line 664:
Java provides a <code>BigDecimal</code> class that supports robust arbitrary precision calculations. That class is demonstrated using the computations required in this task.
 
<langsyntaxhighlight lang="java">
import java.math.BigDecimal;
 
Line 684:
 
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 721:
=={{header|Julia}}==
Julia implements arbitary precision intergers and floating point numbers in its base function.
<langsyntaxhighlight lang="julia">
@assert(big"12345679e63" * BigFloat(81) + big"1e63" == big"1.0e+72")
@assert(big"12345679012345679e54" * BigFloat(81) + big"1e54" == big"1.0e+72")
@assert(big"12345679012345679012345679e45" * BigFloat(81) + big"1e45" == big"1.0e+72")
@assert(big"12345679012345679012345679012345679e36" * BigFloat(81) + big"1e36" == big"1.0e+72")
</syntaxhighlight>
</lang>
All assertions pass.
 
Line 733:
 
Although the BigDecimal type supports multiplication, I've used repeated addition here to be more in tune with the spirit of the task.
<langsyntaxhighlight lang="scala">// version 1.2.10
 
import java.math.BigDecimal
Line 756:
e -= 9
}
}</langsyntaxhighlight>
 
{{out}}
Line 793:
=={{header|Perl}}==
Calculations done in decimal, prints 'Y' for each successful test.
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use Math::Decimal qw(dec_add dec_mul_pow10);
Line 804:
printf "$n:%s ", 10**72 == $sum ? 'Y' : 'N';
$e -= 9;
}</langsyntaxhighlight>
{{out}}
<pre>-7:Y -6:Y -5:Y -4:Y -3:Y -2:Y -1:Y 0:Y 1:Y 2:Y 3:Y 4:Y 5:Y 6:Y 7:Y 8:Y 9:Y 10:Y 11:Y 12:Y 13:Y 14:Y 15:Y 16:Y 17:Y 18:Y 19:Y 20:Y 21:Y
Line 812:
===bigatom===
Note this is decimal-only, and that mpfr.e does not really cope because it cannot hold decimal fractions exactly (though it could probably be fudged with a smidgen of rounding)
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">include</span> <span style="color: #000000;">bigatom</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ba_scale</span><span style="color: #0000FF;">(</span><span style="color: #000000;">200</span><span style="color: #0000FF;">)</span>
Line 829:
<span style="color: #000000;">e</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">9</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</langsyntaxhighlight>-->
{{out|Output (trimmed)}}
(Use the %B format to better see the difference between adding and not adding e1.)
Line 840:
=== any base ===
Uses b_add() and b_mul() from [[Generalised_floating_point_multiplication#Phix]]
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Generic_addition.exw
Line 1,109:
<span style="color: #000000;">e</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">9</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</langsyntaxhighlight>-->
same ouput
 
Line 1,118:
The printed result is the exact difference of 1e72 and the result. So those <code>0</code>s you see are exactly nothing.
 
<langsyntaxhighlight lang="racket">#lang racket
(define (f n (printf printf))
(define exponent (* (- n) 9))
Line 1,143:
(module+ main
(displayln "number in brackets is TOTAL number of digits")
(for ((i (in-range -7 (add1 21)))) (f i)))</langsyntaxhighlight>
 
{{out}}
Line 1,182:
(formerly Perl 6)
As long as all values are kept as rationals (type <code>Rat</code>) calculations are done full precision.
<syntaxhighlight lang="raku" perl6line>my $e = 63;
for -7..21 -> $n {
my $num = '12345679' ~ '012345679' x ($n+7);
Line 1,188:
printf "$n:%s ", 10**72 == $sum ?? 'Y' !! 'N';
$e -= 9;
}</langsyntaxhighlight>
{{out}}
<pre>-7:Y -6:Y -5:Y -4:Y -3:Y -2:Y -1:Y 0:Y 1:Y 2:Y 3:Y 4:Y 5:Y 6:Y 7:Y 8:Y 9:Y 10:Y 11:Y 12:Y 13:Y 14:Y 15:Y 16:Y 17:Y 18:Y 19:Y 20:Y 21:Y
Line 1,213:
└─┐ The number of digits for the precision is automatically adjusted. ┌─┘
└────────────────────────────────────────────────────────────────────┘
<langsyntaxhighlight lang="rexx">/*REXX program performs generalized floating point addition using BCD numbers. */
maxW= linesize() - 1 /*maximum width allowed for displays. */
/*Not all REXXes have the LINESIZE BIF.*/
Line 1,250:
say right(k,3) 'sum=' translate(_, "e", 'E') /*use a lowercase "E" for exponents. */
end /*k*/
/*stick a fork in it, we're all done. */</langsyntaxhighlight>
This REXX program makes use of &nbsp; '''LINESIZE''' &nbsp; REXX program (or BIF) which is used to determine the screen width (or linesize) of the terminal (console).
<br>The &nbsp; '''LINESIZE.REX''' &nbsp; REXX program is included here &nbsp; ───► &nbsp; [[LINESIZE.REX]].<br>
Line 1,320:
 
===any base===
<langsyntaxhighlight lang="rexx">/*REXX program performs generalized floating point addition using BCD numbers. */
parse arg base . /*obtain optional argument from the CL.*/
if base=='' | base=="," then base= 10 /*Not specified? Then use the default.*/
Line 1,502:
numnot: if q==1 then return x; call er53 x
numx: return num( arg(1), arg(2), 1)
p: return subword( arg(1), 1, max(1, words( arg(1) ) - 1) )</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the (base) input of: &nbsp; &nbsp; <tt> 62 </tt>}}
<pre>
Line 1,570:
=={{header|Ruby}}==
No code, it's built in (uses '*' for multiplication):
<langsyntaxhighlight lang="ruby">p 12345679e63 * 81 + 1e63
p 12345679012345679e54 * 81 + 1e54
p 12345679012345679012345679e45 * 81 + 1e45
p 12345679012345679012345679012345679e36 * 81 + 1e36</langsyntaxhighlight>
All result in 1.0e+72.
 
=={{header|Tcl}}==
Tcl does not allow overriding the default mathematical operators (it does allow you to define your own expression engine — this is even relatively simple to do — but this is out of the scope of this task) but it also allows expressions to be written using a Lisp-like prefix form:
<langsyntaxhighlight lang="tcl">namespace path ::tcl::mathop
for {set n -7; set e 63} {$n <= 21} {incr n;incr e -9} {
append m 012345679
puts $n:[+ [* [format "%se%s" $m $e] 81] 1e${e}]
}</langsyntaxhighlight>
The above won't work as intended though; the default implementation of the mathematical operators does not handle arbitrary precision floats (though in fact it will produce the right output with these specific values; this is a feature of the rounding used, and the fact that the exponent remains expressible in an IEEE double-precision float). So here is a version that does everything properly:
<langsyntaxhighlight lang="tcl">namespace eval longfloat {
proc + {num args} {
set num [impl::Tidy $num]
Line 1,664:
}
}
}</langsyntaxhighlight>
Now we can demonstrate (compare with the original code to see how little has changed syntactically):
<langsyntaxhighlight lang="tcl">namespace path longfloat
for {set n -7; set e 63} {$n <= 21} {incr n;incr e -9} {
append m 012345679
puts $n:[+ [* [format "%se%s" $m $e] 81] 1e${e}]
}</langsyntaxhighlight>
{{out|Output (trimmed)}}
<pre>
Line 1,694:
 
Although the BigRat type supports multiplication, repeated addition has been used as in the Kotlin example.
<langsyntaxhighlight ecmascriptlang="wren">import "./big" for BigRat
import "./fmt" for Fmt
 
var repeatedAdd = Fn.new { |br, times|
Line 1,715:
s = t + s
e = e - 9
}</langsyntaxhighlight>
 
{{out}}
9,482

edits