Currency: Difference between revisions

11,827 bytes added ,  12 days ago
added RPL
m (syntax highlighting fixup automation)
(added RPL)
 
(20 intermediate revisions by 9 users not shown)
Line 319:
total 23683000000000006.16
</pre>
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> REM No need for BigNum library.
REM This language uses 80bit (10 bytes!) for real values internally.
Price = 4E15 * 5.50 + 2.0 * 2.86
Tax = Price * .0765
Total = Price + Tax
 
REM Number printing will use 2 decimal places and 21 positions zone
@%=&020215
PRINT "Price = $" Price
PRINT "Tax = $" Tax
PRINT "Total = $" Total</syntaxhighlight>
{{out}}
<pre>Price = $ 22000000000000005.72
Tax = $ 1683000000000000.44
Total = $ 23683000000000006.16</pre>
 
=={{header|Bracmat}}==
Line 552 ⟶ 569:
Total with tax: $23683000000000006.16
</pre>
 
=={{header|Common Lisp}}==
Let us just use the built-in and convenient rationals (which use two bignums for numerator and denominator).
 
<syntaxhighlight lang="lisp">(defun print-$ (rat &key (prefix "") (stream t))
(multiple-value-bind (dollars cents) (truncate rat)
(format stream "~A~D.~D~%" prefix dollars (round (* 100 cents)))))
 
(defun compute-check (order-alist tax-rate)
(let* ((total-before-tax
(loop :for (amount . price) in order-alist
:sum (* (rationalize price) amount)))
(tax (* (rationalize tax-rate) total-before-tax)))
(print-$ total-before-tax :prefix "Total before tax: ")
(print-$ tax :prefix "Tax: ")
(print-$ (+ total-before-tax tax) :prefix "Total with tax: ")))
 
(compute-check '((4000000000000000 . 5.5) (2 . 2.86)) 0.0765)</syntaxhighlight>
 
{{out}}
<pre>Total before tax: 22000000000000005.72
Tax: 1683000000000000.44
Total with tax: 23683000000000006.16</pre>
 
A reader macro can be used as extra nice icing on the cake:
<syntaxhighlight lang="lisp">(defun read-$ (stream char)
(declare (ignore char))
(let* ((str (with-output-to-string (out)
;; TODO: read integer, if dot, read dot and another integer
(loop :for next = (peek-char nil stream t nil t)
:while (or (digit-char-p next) (char= next #\.))
:do (write-char (read-char stream t nil t) out))))
(dot-pos (position #\. str))
(dollars (parse-integer str :end dot-pos))
(cents (if dot-pos
(/ (parse-integer str :start (+ dot-pos 1))
(expt 10 (- (length str) (+ dot-pos 1))))
0)))
(+ dollars cents)))
(set-macro-character #\$ #'read-$ t)
 
(defun print-$ (rat &key (prefix "") (stream t))
(multiple-value-bind (dollars cents) (truncate rat)
(format stream "~A~D.~D~%" prefix dollars (round (* 100 cents)))))
 
(defun compute-check (order-alist tax-rate)
(let* ((total-before-tax
(loop :for (amount . price) in order-alist
:sum (* price amount)))
(tax (* (rationalize tax-rate) total-before-tax)))
(print-$ total-before-tax :prefix "Total before tax: ")
(print-$ tax :prefix "Tax: ")
(print-$ (+ total-before-tax tax) :prefix "Total with tax: ")))
 
(compute-check '((4000000000000000 . $5.5) (2 . $2.86)) 0.0765)</syntaxhighlight>
 
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
Line 777 ⟶ 850:
Tax: 1683000000000000.44 dollars
Total: 23683000000000006.16 dollars
</pre>
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
local fn Lunch_Invoice( burger_price as CFStringRef, burger_amount as CFStringRef, shake_price as CFStringRef, shake_amount as CFStringRef, tax as CFStringRef )
'~'1
DecimalNumberRef burgerPriceDecimal = fn DecimalNumberWithString( burger_price )
DecimalNumberRef burgerAmountDecimal = fn DecimalNumberWithString( burger_amount )
DecimalNumberRef burgersDecimal = fn DecimalNumberByMultiplyingBy( burgerPriceDecimal, burgerAmountDecimal )
DecimalNumberRef shakePriceDecimal = fn DecimalNumberWithString( shake_price )
DecimalNumberRef shakeAmountDecimal = fn DecimalNumberWithString( shake_amount )
DecimalNumberRef shakesDecimal = fn DecimalNumberByMultiplyingBy( shakePriceDecimal, shakeAmountDecimal )
DecimalNumberRef taxDecimal = fn DecimalNumberWithString( tax )
DecimalNumberRef subtotalDecimal = fn DecimalNumberByAdding( burgersDecimal, shakesDecimal )
DecimalNumberRef taxTotalDecimal = fn DecimalNumberByMultiplyingBy( subtotalDecimal, taxDecimal )
DecimalNumberRef adjTaxTotalDecimal = fn DecimalNumberByAdding( taxTotalDecimal, fn DecimalNumberWithString( @"0.01" ) )
DecimalNumberRef billTotalDecimal = fn DecimalNumberByAdding( subtotalDecimal, adjTaxTotalDecimal )
 
CFStringRef burgersString = fn DecimalNumberString( burgersDecimal )
CFStringRef shakesString = fn DecimalNumberString( shakesDecimal )
CFStringRef taxTotalString = fn DecimalNumberString( adjTaxTotalDecimal )
CFStringRef billTotalString = fn DecimalNumberString( billTotalDecimal )
 
printf @"%@", fn StringByPaddingToLength( @"", 55, @"-", 0 )
printf @"Item Price Quantity Cost"
printf @"Hamburgers %6s %18s %18s", fn StringUTF8String( burger_price ), fn StringUTF8String( burger_amount ), fn StringUTF8String( burgersString )
printf @"Milkshakes %6s %18s %18s", fn StringUTF8String( shake_price ), fn StringUTF8String( shake_amount ), fn StringUTF8String( shakesString )
printf @"%@", fn StringByPaddingToLength( @"", 55, @"-", 0 )
printf @"%34s %@", fn StringUTF8String( @"Subtotal:" ), fn DecimalNumberString( subtotalDecimal )
printf @"%35s %@", fn StringUTF8String( @" Tax: " ), fn StringSubstringToIndex( taxTotalString, len(taxTotalString) - 3 )
printf @"%34s %@", fn StringUTF8String( @" Total:" ), fn StringSubstringToIndex( billTotalString, len(billTotalString) - 3 )
end fn
 
NSLog( @"%@", fn WindowPrintViewString( 1 ) )
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
-------------------------------------------------------
Item Price Quantity Cost
Hamburgers 5.50 4000000000000000 22000000000000000
Milkshakes 2.86 2 5.72
-------------------------------------------------------
Subtotal: 22000000000000005.72
Tax: 1683000000000000.44
Total: 23683000000000006.16
 
</pre>
 
Line 1,422 ⟶ 1,543:
=={{header|OCaml}}==
 
Using the [https://githubocaml.comorg/janestreetp/bignumdecimal/0.3.0 Bignumdecimal] library.
 
<syntaxhighlight lang="ocaml">#require "bignum" ;;
let () =
let open Decimal in (* bring all functions and operators into scope locally *)
let s = of_string in
let i = of_int in
 
let p1hamburgers = Bignum.((of_strings "40000000000000004e15") * (of_float_decimals "5.50))" ;;in
let p2milkshakes = Bignum.((of_inti 2) * (of_float_decimals "2.86))" ;;in
let tax_rate = s "7.65e-2" in
let subtotal = hamburgers + milkshakes in
let tax = subtotal * tax_rate in
let total = subtotal + tax in
 
Printf.printf
let r1 = Bignum.(p1 + p2) ;;
"Subtotal: %20s
let r2 = Bignum.(r1 * (of_float_decimal (7.65 /. 100.))) ;;
Tax: %20s
let r3 = Bignum.(r1 + r2) ;;
Total: %20s\n"
 
(to_string (round ~n:2 subtotal))
let my_to_string v =
(to_string (round ~n:2 tax))
Bignum.(v |> round_decimal ~dir:`Nearest ~digits:2
(to_string (round ~n:2 total))
|> to_string_hum ~decimals:2) ;;
</syntaxhighlight>
 
let () =
Printf.printf "before tax: %s\n" (my_to_string r1);
Printf.printf "tax: %s\n" (my_to_string r2);
Printf.printf "total: %s\n" (my_to_string r3);
;;</syntaxhighlight>
{{out}}
<pre>
Subtotal: 22000000000000005.72
$ opam install bignum
Tax: 1683000000000000.44
$ opam install utop
Total: 23683000000000006.16
$ eval $(opam env)
$ utop currency.ml
before tax: 22000000000000005.72
tax: 1683000000000000.44
total: 23683000000000006.16
</pre>
 
Line 1,498 ⟶ 1,618:
{{libheader|Phix/mpfr}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #0080807060A8;">withrequires</span><span style="color: #0000FF;">(</span><span style="color: #008080008000;">javascript_semantics"1.0.4"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (mpfr_get_fixed() busted in 1.0.2|3)</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1.0.0"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (mpfr_set_default_prec[ision] has been renamed)</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #7060A8;">mpfr_set_default_precision</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">20</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ensure accuracy to at least 20 d.p.</span>
Line 1,513 ⟶ 1,632:
<span style="color: #7060A8;">mpfr_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tax</span><span style="color: #0000FF;">,</span><span style="color: #000000;">total_price</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tax</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">total</span><span style="color: #0000FF;">,</span><span style="color: #000000;">total_price</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tax</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Total before tax:%21s26s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">mpfr_get_fixed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">total_price</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">comma_fill</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" Tax:%21s26s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">mpfr_get_fixed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tax</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">comma_fill</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" Total:%21s26s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">mpfr_get_fixed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">total</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">comma_fill</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Total before tax: 22,000,000,000,000,005.72
Total before tax: 22000000000000005.72
             Tax:  1,683,000,000,000,000.44
Tax: 1683000000000000.44
           Total: 23,683,000,000,000,006.16
Total: 23683000000000006.16
</pre>
=== 64 bit ===
As it happens, 64-bit Phix uses 80-bit floats for atoms, which actually have just enough accuracy for this task:
<!--<syntaxhighlight lang="phix">-->
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #000000;">64</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">total_price</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4000000000000000</span><span style="color: #0000FF;">*</span><span style="color: #000000;">5.5</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2.86</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">tax</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">total_price</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.0765</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">total_price</span><span style="color: #0000FF;">+</span><span style="color: #000000;">tax</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Total before tax:%,26.2f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">total_price</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" Tax:%,26.2f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tax</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" Total:%,26.2f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">total</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
with the same output, however (after deleting the first line) under 32-bit (and under p2js) they would incorrectly end in 4.00/0.25/4.00.
 
=={{header|PicoLisp}}==
Line 1,584 ⟶ 1,715:
--------------------
Total 23683000000000006.16</pre>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ $ "bigrat.qky" loadfile ] now!
 
[ 100 * n->v ] is dollars ( n --> n/d )
 
[ n->v v+ ] is cents ( n/d n --> n/d )
 
[ rot n->v v* ] is cost ( n n/d --> n/d )
 
[ $->v drop v* 100 n->v v/ ] is tax ( n/d $ --> n/d )
 
[ 100 n->v v/
2 point$
$ " $" swap join
' [ 2 split nip ] ]do[
dup -3 peek
char . = if done
dup -2 peek
char . = iff
[ char 0 join ]
done
$ ".00" join ] is currency$ ( n/d --> $ )
 
[ currency$ echo$ ] is echocurrency ( n/d --> )
 
 
4000000000000000 5 dollars 50 cents cost
2 2 dollars 86 cents cost v+
 
say "Total price before tax: " 2dup echocurrency cr
2dup $ "7.65" tax
say "Tax: " 2dup echocurrency cr
v+
say "Total price with tax: " echocurrency cr
</syntaxhighlight>
 
{{out}}
 
<pre>Total price before tax: $22000000000000005.72
Tax: $1683000000000000.44
Total price with tax: $23683000000000006.16</pre>
 
=={{header|Racket}}==
Line 1,807 ⟶ 1,984:
total price after tax : 23683000006.16
</pre>
=={{header|RPL}}==
Need for big integers.
{{works with|RPL|HP-49C}}
« →STR
'''IF''' LASTARG 9 ≤ '''THEN''' "0" SWAP + '''END'''
1 OVER SIZE 2 - SUB
LASTARG NIP 1 + DUP 1 + SUB
"$" ROT SIZE LASTARG "0" IFTE +
"." + SWAP +
» '<span style="color:blue">→CURR</span>' STO
« 100 * R→I *
DUP <span style="color:blue">→CURR</span> CLLCD 1 DISP .5 WAIT
» '<span style="color:blue">→PRICE</span>' STO
« DUPDUP FLOOR - EVAL →NUM
0.5 ≥ SWAP CEIL LASTARG FLOOR IFTE
» '<span style="color:blue">→RND</span>' STO
« 100 * R→I
OVER <span style="color:blue">→CURR</span> "TPBT" →TAG
UNROT OVER * 100000 / <span style="color:blue">→RND</span> DUP <span style="color:blue">→CURR</span> "Tax" →TAG
UNROT + <span style="color:blue">→CURR</span> "TPWT" →TAG
» '<span style="color:blue">TAX→</span>' STO
 
4000000000000000 5.50 <span style="color:blue">→PRICE</span>
2 2.86 <span style="color:blue">→PRICE</span> +
7.65 <span style="color:blue">TAX→</span>
{{out}}
<pre>
3: TPBT:"$22000000000000005.72"
2: Tax:"$1683000000000000.44"
1: TPWT:"$23683000000000006.16"
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">require 'bigdecimal/util'
Line 1,877 ⟶ 2,089:
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let cents = (&self.amount * BigInt::from(100)).to_integer();
write!(f, "${}.{:0>2}", &cents / 100, &cents % 100)
}
}
Line 1,885 ⟶ 2,097:
fn new(num: f64) -> Self {
Self {
amount: BigRational::new(((num * 100.0).round() as i64).into(), 100.into())
}
}
Line 2,082 ⟶ 2,294:
{{out}}
net=22000000000000005.72, tax=1683000000000000.44, total=23683000000000006.16
 
=={{header|Unicon}}==
Solution takes advantage of Unicon's FxPt class as well as Unicon's operator overloading extension.
<syntaxhighlight lang="unicon">import math
 
procedure main()
n_burgers := 4000000000000000
n_shakes := 2
 
price := FxPt(5.50) * n_burgers + FxPt(2.86) * n_shakes
tax := (price * FxPt(7.65/100)).round(2)
total := price + tax
 
write(left("Price", 10), "$", right(price.toString(),21))
write(left("Tax", 10), "$", right(tax.toString(),21))
write(left("Total", 10), "$", right(total.toString(),21))
end</syntaxhighlight>{{out}}
<pre>Price $ 22000000000000005.72
Tax $ 1683000000000000.44
Total $ 23683000000000006.16</pre>
 
=={{header|VBA}}==
Line 2,117 ⟶ 2,349:
=={{header|Wren}}==
{{libheader|Wren-big}}
<syntaxhighlight lang="ecmascriptwren">import "./big" for BigRat
 
var hamburgers = BigRat.new("4000000000000000")
1,150

edits