payments nick

18
Payment Nick Vincent neoworks

Upload: neoworks

Post on 14-Jan-2015

50 views

Category:

Economy & Finance


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Payments nick

Payment

Nick Vincent neoworks

Page 2: Payments nick

•  Surely everyone orders and pays the same way as us? •  In mainland Europe it is common to pay for goods by bank transfer •  Brazil charges 60% import tax •  In Japan it is common to have goods delivered and to pay for them later

Worldwide

Page 3: Payments nick

•  3D Secure •  An unpopular inconvenience •  Unusual tax regimes •  US tax calculation is so complex it requires a 3rd party service •  Not charging the right amount •  This is going to upset most people

Problems with payment

Page 4: Payments nick

•  Promotions •  Pricing •  Tax •  So how do we make sure that you are paying the right amount?

Complicating the problem

Page 5: Payments nick

•  Use a double? •     Memory  efficient  •     High  precision  •     Fast  CPU  backed  calcula<ons  •     Secret  rounding  •     But...  rounding  problems,  but  would  we  really  see  those          in  real  life?  

Modelling money

Page 6: Payments nick

•  JVM primitives often have lots of constants to make it easier for us and prevent the use of magic numbers, like MIN_VALUE. double adjustment = -5.0D;double threshold = 10.0D;if(adjustment>=Double.MIN_VALUE && adjustment<=threshold) { System.out.println("Small adjustment");} else { System.out.println("Big adjustment");}

Output: Big adjustment

Useful constants

Page 7: Payments nick

•  Double.MIN_VALUE is not really the minimum value possible. •  It is “A constant holding the smallest positive nonzero value of type double, 2-1074”

Urr, why?

Page 8: Payments nick

•  What does this do?

•  double amount = 100.05; •  double discount = amount * 0.10; •  double total = amount - discount;

•  NumberFormat money = NumberFormat.getCurrencyInstance(); •  System.out.println("Subtotal="+ money.format(amount)); •  System.out.println("Discount=" + money.format(discount)); •  System.out.println("Total=" + money.format(total)); Subtotal=£100.05Discount=£10.00Total=£90.04

Trouble with double

Page 9: Payments nick

•  Subtotal=£100.05 •  Discount=£10.00 •  Total=£90.04

•  But what were the real values hidden from us?

•  Subtotal=100.049999999999997157829056959599256515502 •  Discount=10.005000000000000781597009336110204458236694 •  Total=90.045000000000001705302565824240446090698

•  Double has helpfully rounded down for us. The rounding behaviour of NumberFormat can be controlled by RoundingMode in JDK6+.

Explain that

Page 10: Payments nick

•  But that was a multiplication, surely that can’t happen to a simple addition?

•  boolean x = (0.7d+0.1d) == (0.9d-0.1d);

•  System.out.println(x);

false

0.7d+0.1d == 0.7999999999999999

0.9d-0.1d == 0.8

Double trouble

Page 11: Payments nick

•  What could this really mean, it’s just a penny.

Tiny amounts of money

Woman eaten by a computer

Gorman’s salami slicing Blackmail

Ersatz Kryptonite Bad superman

Weather control satellite

Page 12: Payments nick

•  It’s obviously not right and very salient •  It undermines the end customer’s confidence •  Your client thinks you can’t even do basic arithmetic right - “get me a calculator, I’ll show them how to add up”

So why is this really bad?

Page 13: Payments nick

•  So why don’t we just use a long instead, like all the banks do? •  System needs to be engineered from the ground up to use this approach •  Can’t easily carry fractional units through calculation •  End users/administrators don’t understan the approach when looking at logs and managing prices

The long way around

Page 14: Payments nick

•  Infinite precision •  Internal string representation •  Slow, but is this really going to affect your system?

Enter big decimal

Page 15: Payments nick

Here’s a simple example: •  BigDecimal amount = new BigDecimal(“10”); •  BigDecimal discount = new BigDecimal(“2”);

•  amount.subtract(discount);

•  System.out.println(amount);

Output: 10

BigDecimals are immutable, so the new amount is calculated and immediately discarded.

Simple API...

Page 16: Payments nick

A matter of scale

Page 17: Payments nick

•  You may have legacy code using doubles •  How do we interface with it? double discount = 0.1D; // Call your legacy system here

System.out.println(new BigDecimal(discount));

Output: 0.1000000000000000055511151231257827021181583404541015625 System.out.println(BigDecimal.valueOf(discount));

Output: 0.1

Bridging the gap

Page 18: Payments nick