Currency
Show how you might represent currency in a simple example, using a data type that represent exact values of dollars and cents. Note for example that the IEEE 754 binary floating point representations of numbers like 2.86 and .0765 are not exact.
For this example, data will be two items with prices in dollars and cents, a quantity for each, and a tax rate. Use the values 4000000000000000 hamburgers at $5.50 each, 2 milkshakes at $2.86 each, and a tax rate of 7.65%. (That number of hamburgers is a 4 with 15 zeros after it. The number is contrived to exclude naïve task solutions using 64 bit floating point types.) Compute and output the total price before tax, the tax, and the total with tax, and show results on this page. The tax value must be computed by rounding to the nearest whole cent and this exact value must be added to the total price before tax. The output must show dollars and cents with a decimal point. The three results displayed should be 22000000000000005.72, 1683000000000000.44, and 23683000000000006.16. Dollar signs and thousands separators are optional.
AWK
version 1
<lang AWK>
- syntax: GAWK -M -f CURRENCY.AWK
- using GNU Awk 4.1.1, API: 1.1 (GNU MPFR 3.1.2, GNU MP 5.1.2)
BEGIN {
PREC = 100 hamburger_p = 5.50 hamburger_q = 4000000000000000 hamburger_v = hamburger_p * hamburger_q milkshake_p = 2.86 milkshake_q = 2 milkshake_v = milkshake_p * milkshake_q subtotal = hamburger_v + milkshake_v tax = subtotal * .0765 printf("%-9s %8s %18s %22s\n","item","price","quantity","value") printf("hamburger %8.2f %18d %22.2f\n",hamburger_p,hamburger_q,hamburger_v) printf("milkshake %8.2f %18d %22.2f\n\n",milkshake_p,milkshake_q,milkshake_v) printf("%37s %22.2f\n","subtotal",subtotal) printf("%37s %22.2f\n","tax",tax) printf("%37s %22.2f\n","total",subtotal+tax) exit(0)
} </lang>
Output:
item price quantity value hamburger 5.50 4000000000000000 22000000000000000.00 milkshake 2.86 2 5.72 subtotal 22000000000000005.72 tax 1683000000000000.41 total 23683000000000006.13
version 2
<lang AWK>
- syntax: GAWK -M -f CURRENCY2.AWK
- using GNU Awk 4.1.1, API: 1.1 (GNU MPFR 3.1.2, GNU MP 5.1.2)
- INT is used to define values and do math; results then converted to FLOAT
BEGIN {
PREC = 100 hamburger_p = 550 hamburger_q = 4000000000000000 hamburger_v = hamburger_p * hamburger_q milkshake_p = 286 milkshake_q = 2 milkshake_v = milkshake_p * milkshake_q subtotal = hamburger_v + milkshake_v tax = subtotal * 765 subtotal /= 100 tax /= 1000000 printf("%-9s %8s %18s %22s\n","item","price","quantity","value") printf("hamburger %8.2f %18d %22.2f\n",hamburger_p/100,hamburger_q,hamburger_v/100) printf("milkshake %8.2f %18d %22.2f\n\n",milkshake_p/100,milkshake_q,milkshake_v/100) printf("%37s %22.2f\n","subtotal",subtotal) printf("%37s %22.2f\n","tax",tax) printf("%37s %22.2f\n","total",subtotal+tax) exit(0)
} </lang>
Output:
item price quantity value hamburger 5.50 4000000000000000 22000000000000000.00 milkshake 2.86 2 5.72 subtotal 22000000000000005.72 tax 1683000000000000.44 total 23683000000000006.16
C#
The built in C# type decimal has a max value of 79228162514264337593543950335. <lang csharp>using System; using System.Collections.Generic;
namespace Currency {
class Program { static void Main(string[] args) { MenuItem hamburger = new MenuItem() { Name = "Hamburger", Price = 5.5M }; MenuItem milkshake = new MenuItem() { Name = "Milkshake", Price = 2.86M };
IList<CartItem> cart = new List<CartItem>(); cart.Add(new CartItem() { item = hamburger, quantity = 4000000000000000 }); cart.Add(new CartItem() { item = milkshake, quantity = 2 });
decimal total = CalculateTotal(cart);
Console.WriteLine(string.Format("Total before tax: {0:C}", total));
// Add Tax decimal tax = total * 0.0765M;
Console.WriteLine(string.Format("Tax: {0:C}", tax));
total += tax;
Console.WriteLine(string.Format("Total with tax: {0:C}", total)); }
private static decimal CalculateTotal(IList<CartItem> cart) { decimal total = 0M;
foreach (CartItem item in cart) { total += item.quantity * item.item.Price; }
return total; }
private struct MenuItem { public string Name { get; set; } public decimal Price { get; set; } }
private struct CartItem { public MenuItem item { get; set; } public decimal quantity { get; set; } } }
}</lang>
- Output:
Total before tax: $22,000,000,000,000,005.72 Tax: $1,683,000,000,000,000.44 Total with tax: $23,683,000,000,000,006.16
Clojure
<lang clojure>(require '[clojurewerkz.money.amounts :as ma]) (require '[clojurewerkz.money.currencies :as mc]) (require '[clojurewerkz.money.format :as mf])
(let [burgers (ma/multiply (ma/amount-of mc/USD 5.50) 4000000000000000)
milkshakes (ma/multiply (ma/amount-of mc/USD 2.86) 2) pre-tax (ma/plus burgers milkshakes) tax (ma/multiply pre-tax 0.0765 :up)] (println "Total before tax: " (mf/format pre-tax)) (println " Tax: " (mf/format tax)) (println " Total with tax: " (mf/format (ma/plus pre-tax tax))))</lang>
- Output:
Total before tax: $22,000,000,000,000,005.72 Tax: $1,683,000,000,000,000.44 Total with tax: $23,683,000,000,000,006.16
COBOL
COBOL supports up to 31 digits of precision so won't need any fancy currency/BigInteger types!
<lang cobol> >>SOURCE FREE IDENTIFICATION DIVISION. PROGRAM-ID. currency-example.
DATA DIVISION. WORKING-STORAGE SECTION. 01 Burger-Price CONSTANT 5.50. 01 Milkshake-Price CONSTANT 2.86. 01 num-burgers PIC 9(18) VALUE 4000000000000000. 01 num-milkshakes PIC 9(18) VALUE 2. 01 tax PIC 9(18)V99. 01 tax-edited PIC $(17)9.99. 01 Tax-Rate CONSTANT 7.65. 01 total PIC 9(18)V99. 01 total-edited PIC $(17)9.99.
PROCEDURE DIVISION.
COMPUTE total, total-edited = num-burgers * Burger-Price + num-milkshakes * Milkshake-Price DISPLAY "Total before tax: " total-edited
COMPUTE tax, tax-edited = total * (Tax-Rate / 100) DISPLAY " Tax: " tax-edited
ADD tax TO total GIVING total-edited DISPLAY " Total with tax: " total-edited .
END PROGRAM currency-example.</lang>
- Output:
Total before tax: $22000000000000005.72 Tax: $1683000000000000.43 Total with tax: $23683000000000006.15
Go
<lang go>package main
import (
"fmt" "log" "math/big"
)
// DC for dollars and cents. Value is an integer number of cents. type DC int64
func (dc DC) String() string {
d := dc / 100 if dc < 0 { dc = -dc } return fmt.Sprintf("%d.%02d", d, dc%100)
}
// Extend returns extended price of a unit price. func (dc DC) Extend(n int) DC {
return dc * DC(n)
}
var one = big.NewInt(1) var hundred = big.NewRat(100, 1)
// ParseDC parses dollars and cents as a string into a DC. func ParseDC(s string) (DC, bool) {
r, ok := new(big.Rat).SetString(s) if !ok { return 0, false } r.Mul(r, hundred) if r.Denom().Cmp(one) != 0 { return 0, false } return DC(r.Num().Int64()), true
}
// TR for tax rate. Value is an an exact rational. type TR struct {
*big.Rat
} func NewTR() TR {
return TR{new(big.Rat)}
}
// SetString overrides Rat.SetString to return the TR type. func (tr TR) SetString(s string) (TR, bool) {
if _, ok := tr.Rat.SetString(s); !ok { return TR{}, false } return tr, true
}
var half = big.NewRat(1, 2)
// Tax computes a tax amount, rounding to the nearest cent. func (tr TR) Tax(dc DC) DC {
r := big.NewRat(int64(dc), 1) r.Add(r.Mul(r, tr.Rat), half) return DC(new(big.Int).Div(r.Num(), r.Denom()).Int64())
}
func main() {
hamburgerPrice, ok := ParseDC("5.50") if !ok { log.Fatal("Invalid hamburger price") } milkshakePrice, ok := ParseDC("2.86") if !ok { log.Fatal("Invalid milkshake price") } taxRate, ok := NewTR().SetString("0.0765") if !ok { log.Fatal("Invalid tax rate") }
totalBeforeTax := hamburgerPrice.Extend(4000000000000000) + milkshakePrice.Extend(2) tax := taxRate.Tax(totalBeforeTax) total := totalBeforeTax + tax
fmt.Printf("Total before tax: %22s\n", totalBeforeTax) fmt.Printf(" Tax: %22s\n", tax) fmt.Printf(" Total: %22s\n", total)
}</lang>
- Output:
Total before tax: 22000000000000005.72 Tax: 1683000000000000.44 Total: 23683000000000006.16
J
We use a naive implementation with arbitrary precision (rational) numbers:
<lang j>require 'format/printf' fmtD=: 0j2&": NB. format rational as decimal
Items=: ;: 'Hamburger Milkshake' Quantities=: x: 4000000000000000 2 Prices=: x: 5.50 2.86 Tax_rate=: x: 0.0765 Values=: Quantities * Prices Subtotal=: +/ Values Tax=: Tax_rate * Subtotal Total=: Subtotal + Tax
OutputTemplate=: noun define Item Price Quantity Value %9s %8s %20d %22s %9s %8s %20d %22s
------------------------------- Subtotal: %20s Tax: %20s Total: %20s
)
Vals=: (,Items ,. (fmtD&.> Prices) ,. (<"0 Quantities) ,. (fmtD&.> Values)) , fmtD&.> Subtotal,Tax,Total OutputTemplate printf Vals</lang>
- Output:
Item Price Quantity Value Hamburger 5.50 4000000000000000 22000000000000000.00 Milkshake 2.86 2 5.72 ------------------------------- Subtotal: 22000000000000005.72 Tax: 1683000000000000.44 Total: 23683000000000006.16
Java
<lang java>import java.math.*; import java.util.*;
public class Currency {
final static String taxrate = "7.65";
enum MenuItem {
Hamburger("5.50"), Milkshake("2.86");
private MenuItem(String p) { price = new BigDecimal(p); }
public final BigDecimal price; }
public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH);
MathContext mc = MathContext.DECIMAL128;
Map<MenuItem, BigDecimal> order = new HashMap<>(); order.put(MenuItem.Hamburger, new BigDecimal("4000000000000000")); order.put(MenuItem.Milkshake, new BigDecimal("2"));
BigDecimal subtotal = BigDecimal.ZERO; for (MenuItem it : order.keySet()) subtotal = subtotal.add(it.price.multiply(order.get(it), mc));
BigDecimal tax = new BigDecimal(taxrate, mc); tax = tax.divide(new BigDecimal("100"), mc); tax = subtotal.multiply(tax, mc);
System.out.printf("Subtotal: %20.2f%n", subtotal); System.out.printf(" Tax: %20.2f%n", tax); System.out.printf(" Total: %20.2f%n", subtotal.add(tax)); }
}</lang>
Subtotal: 22000000000000005.72 Tax: 1683000000000000.44 Total: 23683000000000006.16
Perl 6
No need for a special type in Perl 6, since the Rat type is used for normal fractions. (In order to achieve imprecision, you have to explicitly use scientific notation, or use the Num type, or calculate a result that requires a denominator in excess of 2 ** 64. (There's no limit on the numerator.)) <lang perl6>my @check = q:to/END/.lines.map: { [.split(/\t/)] };
Hamburger 5.50 4000000000000000 Milkshake 2.86 2 END
my $tax-rate = 0.0765;
my $fmt = "%-10s %8s %18s %22s\n";
printf $fmt, <Item Price Quantity Extension>;
my $subtotal = [+] @check.map: -> [$item,$price,$quant] {
my $extension = $price * $quant; printf $fmt, $item, $price, $quant, fix2($extension); $extension;
}
printf $fmt, , , , '-----------------'; printf $fmt, , , 'Subtotal ', $subtotal;
my $tax = ($subtotal * $tax-rate).round(0.01); printf $fmt, , , 'Tax ', $tax;
my $total = $subtotal + $tax; printf $fmt, , , 'Total ', $total;
- make up for lack of a Rat fixed-point printf format
sub fix2($x) { ($x + 0.001).subst(/ <?after \.\d\d> .* $ /, ) }</lang>
- Output:
Item Price Quantity Extension Hamburger 5.50 4000000000000000 22000000000000000.00 Milkshake 2.86 2 5.72 ----------------- Subtotal 22000000000000005.72 Tax 1683000000000000.44 Total 23683000000000006.16
Python
This uses Pythons decimal module, (and some copying of names from the Perl 6 example).
<lang python>from decimal import Decimal as D from collections import namedtuple
Item = namedtuple('Item', 'price, quant')
items = dict( hamburger=Item(D('5.50'), D('4000000000000000')),
milkshake=Item(D('2.86'), D('2')) )
tax_rate = D('0.0765')
fmt = "%-10s %8s %18s %22s" print(fmt % tuple('Item Price Quantity Extension'.upper().split()))
total_before_tax = 0 for item, (price, quant) in sorted(items.items()):
ext = price * quant print(fmt % (item, price, quant, ext)) total_before_tax += ext
print(fmt % (, , , '--------------------')) print(fmt % (, , 'subtotal', total_before_tax))
tax = (tax_rate * total_before_tax).quantize(D('0.00')) print(fmt % (, , 'Tax', tax))
total = total_before_tax + tax print(fmt % (, , , '--------------------')) print(fmt % (, , 'Total', total))</lang>
- Output:
ITEM PRICE QUANTITY EXTENSION hamburger 5.50 4000000000000000 22000000000000000.00 milkshake 2.86 2 5.72 -------------------- subtotal 22000000000000005.72 Tax 1683000000000000.44 -------------------- Total 23683000000000006.16
Racket
Racket can handle fractions. To read the decimals numbers as fractions instead of floating point numbers, they must start with #e. For example #e.3 -> 3/10 and .3 ->3E-1. The main problem is rounding correctly and this part is handled in cents-*, that implements a multiplication that rounds to the cents. The rest of the program is only formatting. <lang Racket>#lang racket (define (cents-* x y)
(/ (round (* 100 x y)) 100))
(struct item (name count price))
(define (string-pad-right len . strs)
(define all (apply string-append strs)) (string-append all (make-string (- len (string-length all)) #\space)))
(define (string-pad-left len . strs)
(define all (apply string-append strs)) (string-append (make-string (- len (string-length all)) #\space) all))
(define (show-formated name count price total)
(printf "~a ~a ~a -> ~a\n" (string-pad-right 10 name) (string-pad-left 18 count) (string-pad-left 8 price) (string-pad-left 23 total) ))
(define (show-item it)
(show-formated (item-name it) (~r (item-count it)) (string-append "$" (~r (item-price it) #:precision '(= 2))) (string-append "$" (~r (cents-* (item-count it) (item-price it)) #:precision '(= 2))) ))
(define (show-total all tax-rate)
(define net (for/sum ([it (in-list all)]) (cents-* (item-count it) (item-price it)))) (define tax (cents-* net tax-rate)) (show-formated "" "" "net" (string-append "$" (~r net #:precision '(= 2)))) (show-formated "" "" "tax" (string-append "$" (~r tax #:precision '(= 2)))) (show-formated "" "" "total" (string-append "$" (~r (+ net tax) #:precision '(= 2)))) )
(define hamburger (item "hamburger" 4000000000000000 #e5.50)) (define milkshake (item "milkshake" 2 #e2.86)) (define all (list hamburger milkshake))
(for-each show-item all) (newline) (show-total all (/ #e7.65 100))</lang>
- Output:
hamburger 4000000000000000 $5.50 -> $22000000000000000.00 milkshake 2 $2.86 -> $5.72 net -> $22000000000000005.72 tax -> $1683000000000000.44 total -> $23683000000000006.16
REXX
REXX uses characters to represent everything, including all forms of numbers. So what is expressed as a literal (characters) is what REXX uses. Essentially, it can be thought of as decimal.
without commas
Programming note: the tax rate can be expressed with or without a percent (%) suffix. <lang rexx>/*REXX program shows a method of computing the total price and tax for items. */ numeric digits 200 /*let's get ka-razy.*/ taxRate= 7.65 /*# is: nn or nn% */ if right(taxRate,1)\=='%' then taxRate=taxRate/100 /*handle plain tax#.*/ taxRate=strip(taxRate,,'%') /*strip % (if any).*/ item. =; items=0 /*zero out register.*/ item.1 = '4000000000000000 $5.50 hamburger' item.2 = ' 2 $2.86 milkshake' say center('quantity',22) center('item',22) center('price',22) hdr=left(, 27,'─') left(, 20,'─') left(, 27,'─'); say hdr total=0
do j=1 while item.j\== /*calc. total & tax.*/ parse var item.j quantity price thing /*ring up an item. */ items=items+quantity /*tally the # items. */ price = translate(price,,'$') /*maybe scrub out $. */ subtotal = quantity * price /*calculate subtotal.*/ total = total + subtotal /*calc. running total*/ say right(quantity,27) left(thing,20) show$(subtotal) end /*j*/
say /*display a blank line for separator. */ say translate(hdr, '═', "─") /*display the separator part of the hdr*/ tax=format(total*taxRate,,2) /*round the total tax for all the items*/ say right(items "(items)",35) right('total=',12) show$(total) say right('tax at' (taxRate*100/1)"%=", 48) show$(tax) say say right('grand total=', 48) show$(total+tax) exit /*stick a fork in it, we're all done. */ /*────────────────────────────────────────────────────────────────────────────*/ show$: return right('$' || arg(1),22) /*right-justify and format a $total. */</lang> output (attempting to mimic a check-out register to some degree):
quantity item price ────────────────────── ────────────────────── ────────────────────── 4000000000000000 hamburger $22000000000000000.00 2 milkshake $5.72 ══════════════════════ ══════════════════════ ══════════════════════ 4000000000000002 (items) total= $22000000000000005.72 tax at 7.65%= $1683000000000000.44 grand total= $23683000000000006.16
with commas
<lang rexx>/*REXX program shows a method of computing the total price and tax for items. */ numeric digits 200 /*let's get ka-razy.*/ taxRate= 7.65 /*# is: nn or nn% */ if right(taxRate,1)\=='%' then taxRate=taxRate/100 /*handle plain tax#.*/ taxRate=strip(taxRate,,'%') /*strip % (if any).*/ item. =; items=0 /*zero out register.*/ item.1 = '4000000000000000 $5.50 hamburger' item.2 = ' 2 $2.86 milkshake' say center('quantity',27) center('item',20) center('price',27) hdr=left(, 27,'─') left(, 20,'─') left(, 27,'─'); say hdr total=0
do j=1 while item.j\== /*calc. total & tax.*/ parse var item.j quantity price thing /*ring up an item. */ items=items+quantity /*tally the # items. */ price = translate(price,,'$') /*maybe scrub out $. */ subtotal = quantity * price /*calculate subtotal.*/ total = total + subtotal /*calc. running total*/ say right(commas(quantity),27) left(thing,20) show$(subtotal) end /*j*/
say /*display a blank line for separator. */ say translate(hdr, '═', "─") /*display the separator part of the hdr*/ tax=format(total*taxRate,,2) /*round the total tax for all the items*/ say right(commas(items "(items)"),35) right('total=',12) show$(total) say right('tax at' (taxRate*100/1)"%=", 48) show$(tax) say say right('grand total=', 48) show$(total+tax) exit /*stick a fork in it, we're all done. */ /*────────────────────────────────────────────────────────────────────────────*/ commas: procedure; parse arg _; n=_'.9'; #=123456789; b=verify(n,#,"M")
e=verify(n,#'0',,verify(n,#"0.",'M'))-4 do j=e to b by -3; _=insert(',',_,j); end /*j*/; return _
/*────────────────────────────────────────────────────────────────────────────*/ show$: return right(commas('$' || arg(1)),27) /*right-justify and format a #.*/</lang> output with commas in the larger numbers:
quantity item price ─────────────────────────── ──────────────────── ─────────────────────────── 4,000,000,000,000,000 hamburger $22,000,000,000,000,000.00 2 milkshake $5.72 ═══════════════════════════ ════════════════════ ═══════════════════════════ 4,000,000,000,000,002 (items) total= $22,000,000,000,000,005.72 tax at 7.65%= $1,683,000,000,000,000.44 grand total= $23,683,000,000,000,006.16
Scala
Locale is manipulated to demonstrate the behavior with other currencies.
<lang scala>import java.text.NumberFormat import java.util.Locale
object SizeMeUp extends App {
val menu: Map[String, (String, Double)] = Map("burg" ->("Hamburger XL", 5.50), "milk" ->("Milkshake", 2.86)) val order = List((4000000000000000L, "burg"), (2L, "milk"))
Locale.setDefault(new Locale("ru", "RU"))
val (currSymbol, tax) = (NumberFormat.getInstance().getCurrency.getSymbol, 0.0765)
def placeOrder(order: List[(Long, String)]) = { val totals = for ((qty, article) <- order) yield { val (desc, itemPrize) = menu(article) val (items, post) = (qty, qty * BigDecimal(itemPrize)) println(f"$qty%16d\t$desc%-16s\t$currSymbol%4s$itemPrize%6.2f\t$post%,25.2f") (items, post) } totals.foldLeft((0L, BigDecimal(0))) { (acc, n) => (acc._1 + n._1, acc._2 + n._2)} }
val (items, beforeTax) = placeOrder(order)
println(f"$items%16d\t${"ordered items"}%-16s${'\t' + " Subtotal" + '\t'}$beforeTax%,25.2f")
val taxation = beforeTax * tax println(f"${" " * 16 + '\t' + " " * 16 + '\t' + f"${tax * 100}%5.2f%% tax" + '\t'}$taxation%,25.2f") println(f"${" " * 16 + '\t' + " " * 16 + '\t' + "Amount due" + '\t'}${beforeTax + taxation}%,25.2f")
}</lang>
- Output:
4000000000000000 Hamburger XL руб. 5,50 22 000 000 000 000 000,00 2 Milkshake руб. 2,86 5,72 4000000000000002 ordered items Subtotal 22 000 000 000 000 005,72 7,65% tax 1 683 000 000 000 000,44 Amount due 23 683 000 000 000 006,16 Process finished with exit code 0
Tcl
<lang tcl>package require math::decimal
namespace import math::decimal::*
set hamburgerPrice [fromstr 5.50] set milkshakePrice [fromstr 2.86] set taxRate [/ [fromstr 7.65] [fromstr 100]]
set burgers 4000000000000000 set shakes 2 set net [+ [* [fromstr $burgers] $hamburgerPrice] [* [fromstr $shakes] $milkshakePrice]] set tax [round_up [* $net $taxRate] 2] set total [+ $net $tax]
puts "net=[tostr $net], tax=[tostr $tax], total=[tostr $total]"</lang>
- Output:
net=22000000000000005.72, tax=1683000000000000.44, total=23683000000000006.16
zkl
zkl Ints are 64 bits, so we have 18 digits to play with. So, just multiply bucks by 100 and be careful when doing tax calculations.
<lang zkl>var priceList=D("hamburger",550, "milkshake",286); var taxRate=765; // percent*M const M=0d10_000;
fcn toBucks(n){ "$%,d.%02d".fmt(n.divr(100).xplode()) } fcn taxIt(n) { d,c:=n.divr(M).apply('*(taxRate)); d + (c+5000)/M; } fcn calcTab(items){ // (hamburger,15), (milkshake,100) ...
items=vm.arglist; fmt:="%-10s %8s %18s %26s"; fmt.fmt("Item Price Quantity Extension".split().xplode()).println();
totalBeforeTax:=0; foreach item,n in (items.sort(fcn(a,b){ a[0]<b[0] })){ price:=priceList[item]; t:=price*n; fmt.fmt(item,toBucks(price),n,toBucks(t)).println(); totalBeforeTax+=t; } fmt.fmt("","","","--------------------").println(); fmt.fmt("","","subtotal",toBucks(totalBeforeTax)).println();
tax:=taxIt(totalBeforeTax); fmt.fmt("","","Tax",toBucks(tax)).println();
fmt.fmt("","","","--------------------").println(); fmt.fmt("","","Total",toBucks(totalBeforeTax + tax)).println();
}</lang> <lang zkl>calcTab(T("milkshake",2),T("hamburger",4000000000000000));</lang>
- Output:
Item Price Quantity Extension hamburger $5.50 4000000000000000 $22,000,000,000,000,000.00 milkshake $2.86 2 $5.72 -------------------- subtotal $22,000,000,000,000,005.72 Tax $1,683,000,000,000,000.44 -------------------- Total $23,683,000,000,000,006.16