[Music]
excited to be here cool hi so I'm Megan
I am a software engineer at JAXA in
Sydney and I'm here today to talk to you
all about numbers in general but also
specifically in JavaScript and to have a
little bit of fun with it I'm gonna put
it in the context of Beyonce a little
bit
can I see who here is a fan of Beyonce
can't actually see any of you so I'm
just gonna assume you're all fans of
Beyonce and you're gonna love this talk
so I hope you are ready to learn so
let's go back to basics what actually is
a number well a number is an abstract
concept which we use to count measure
label and identify things we kind of use
them every day
they're pretty familiar concept and to
help us kind of group them in and
understand them we can classify them so
we can group them into certain
categories so we can start off with
natural numbers which are our positive
whole numbers integers we have integers
which is negative and positive whole
numbers and includes 0 we have rational
numbers which numbers that can be
expressed as fractions irrational
numbers and numbers which cannot be
expressed as fractions such as pie or
the square root of 2 and we also have
real numbers so real numbers are a
superset of all of the above categories
and basically represent any number that
you can see on the number line we also
have complex numbers transcendental
numbers imaginary infinity and negative
infinity infinitesimally it's real none
of which I know anything about so not
going to go there so just as we can
classify numbers
in two different ways we can also
represent them in different ways so when
I talk about representation I just mean
how we communicate the numbers that were
using so in human languages if I asked
you to think of the number 8 many people
here would imagine in the Arabic numeral
eight some of us might imagine bar the
Mandarin Chinese characters some of us
might may think of us ah which is the
Hindi number of eight so all of these
are actually the same thing they're just
different symbols which we use to
represent the number eight and apologies
if I've just like butchered the
pronunciation of those feel free to come
and correct me afterwards so just as we
can represent numbers in different ways
in human languages we can also represent
them in different ways in JavaScript so
in JavaScript there are five ways that
we can represent numbers we have our
standard base 10 so if we imagine that
number 1234567 we can also represent
that as a binary number which is base to
octal which is base 8 hexadecimal which
is base 16 you'll use that a lot if
you're working with CSS as well and
scientific notation so that little so
this is what we use when we are handling
really large numbers and that a just
means like times 10 to the power of 6 in
this case so what is a number in
JavaScript well just as a girl has to
have her standards so to does a
programming language and in JavaScript
we follow the OEE
754 standard for floating-point
arithmetic that's the Institute of
Electrical and Electronic engineers it's
a super long really dry document if
you're having trouble sleeping I can
recommend it it's very interesting I
just don't have the the ability to read
that kind of document power to you if
you do but basically it
outlines how numbers are implemented in
JavaScript and gives us a reason why
zero point one plus zero point two does
not equal zero point 3 which is
everyone's favorite JavaScript joke
so the ieee-754 specifies the
implementation of floating-point
arithmetic in JavaScript which is how we
represent decimal points in binary and
it allows us to represent real numbers
as an approximation to support a
trade-off between range and precision so
when I talk about range and precision
computers have limited space they're not
that amazing
sorry no offense so when I talk about
range in JavaScript we have a range of
numbers that's like the size of the set
that we can represent so we can
represent from about negative 9
quadrillion all the way up to positive 9
quadrillion so that's a pretty decent
sample size and when I talk about
precision I mean in JavaScript we can
represent numbers safely to 17 decimal
places beyond that it'll just get kind
of wacky and because computers have
limited space we have to make a
trade-off between range and precision we
can either have greater range or greater
precision we can't really have both
unfortunately so computers are super
basic to you guys
this says hello Singapore in binary so
regardless of how you write your number
everything in your computer is going to
be stored in binary it's all just ones
and zeros but we can't have decimal
points in binary decimal coming from the
word deco meaning 10 binary is based too
so we can't really represent decimal
points safely so floating-point
arithmetic tries to account for that so
let's think about our number 1 million
230 4567 underneath that is the
representation of that number in binary
floating-point
we have 64 bits so 64 individual digits
and it's helpful to kind of think about
this in terms of scientific notation if
you're already familiar with it to break
down these bits so the first bit
represents the sign if it's a zero it's
a positive number if it's a 1 it's a
negative number the next 11 bits
represent the exponent so how far along
the decimal place should be in this case
it would be like six points along six
places alone and we also have the
significant or mantissa which actually
represents the the like actual digits of
the number so let's have a look a closer
look at everybody's favorite JavaScript
bug when I was a kid one of my maths
teachers always used to tell me that
calculators are never wrong humans are
yeah that's all I have to say about that
mr. Edwards so when we are representing
numbers in floating-point arithmetic we
can represent integers super-easy it's
fine the conversion to binary is totally
easy but when we start representing
fractions things become a little more
difficult so if we were trying to
represent say one tenth in binary binary
is based to so representing one out of
ten in a system that only counts up to
two it's gonna present some
complications let's think about a third
when we represent a third in decimal we
round it
we don't say 0.33 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 for the rest of our lives we
just say 0.3 0.33 but as anyone who's
tried to like implement a three column
layout grid layout and CSS we'll know
it's ready 33% x 3 doesn't equal 100%
it's always that pesky little 1% so our
0.1 plus 0.2 problem is similar to this
if we think about 0.1 represented in
decimal it's easy 0.1 let's convert that
to binary ok
that's a lot more complicated I did say
that we don't have decimal points in
binary that's not a decimal point
it's a radix point a radix binary point
so it's a similar concept but just in
base 2 we're not going to get into that
but if you look at this representation
you'll see it's zero point zero zero
zero one one zero zero one one zero zero
one one zero zero and that repetition
just keeps on going
but because we only have 64 bits we only
have a certain amount of space to store
this number we have to round it at some
point and so when we take that rounded
binary representation of 0.1 and convert
it back to decimal
we get this so that's not 0.1 hence this
problem so it's a rounding error how big
a problem is this really if I was trying
to measure 1 centimeter and I had 0.16
zeros for centimeters of era that would
be 0.9 0 3 times as long as a glucose
molecule okay that seems pretty tiny
let's go bigger if I were trying to
measure a kilometer and I had a margin
of error of 0.16 0 4 kilometers that
would be zero point twenty one zero
times as long as the distance from Earth
to the Moon
okay not big enough let's go big or go
home if I were trying to measure a
Lightyear that's the distance that light
travels in a year and I had a margin of
zero margin of error of 0.16 zero four
light-years I'd be about thirty eight
point three eight centimeters off or
about the height of a standard bowling
pin things you learn so in most cases
this degree of accuracy is really just
not gonna be that important
we don't usually need to know a value to
17 decimal places if we're creating a
shopping cart for instance does your
user really need to know their cart
total to 17 decimal places no they need
to know it's like 2 maximum so we can
just round it and we can just round it
really easily using the rounding methods
inside of the math object so we've
talked a bit about precision now let's
move on to range size really does matter
in my defense Charlie started the willy
jokes yesterday so I'm just carrying on
from her work
so I mentioned that we have a trade-off
between range and precision and when I
mentioned our range I said we have a
range in JavaScript of about negative
nine quadrillion through two positive
nine quadrillion but I wasn't telling
the entire truth way to build trust cool
so if I went into my JavaScript console
and I typed in 1.7 times 10 to the power
of 308 I'd get that number back so
obviously I can represent that number
that's way bigger than nine quadrillion
nine quadrillions only like 16 zeros and
this has 308 that's massive but if I go
1.8 to the power times 10 to the power
of 308 any infinity I'm confused
I really remember that being how Matz
works but okay so javascript actually
has a maximum value and you can access
that inside of the number object and
it's one point seven nine seven six nine
all the rest of those numbers times 10
to the power of 308 so that's a really
big number and for really big numbers we
have naming conventions so like a
million a billion a quadrillion and
those naming conventions go all the way
up to a number that is followed by 303
zeroes which is called a Santa lien so
JavaScript actually exceeds naming
conventions like that's massive that's
huge that's a pretty good range if
you're still not convinced that that's a
good range three point two eight times
ten to the power of 80 is a number of
particles in the universe so if you're
using any numbers bigger than that what
are you doing stop I'm gonna create a
black hole or something if you are using
numbers bigger than that like tell me I
want to know what you're doing for real
that's cool so we have no business using
numbers greater than that maximum number
this is this is fine
so we have a massive range up to three
hundred and eight zeros but we can't
safely represent numbers beyond this
nine quadrillion that I'm keep banging
on about so in JavaScript we have a
maximum and minimum safe integers and
that's that nine quadrillion value but
if we move me on those values things get
a little bit weird all right we've got
our maximum safe integer we just pay
attention to the last three digits
because the rest of it it's just too
much
it ends in nine nine one all right let's
try to do some maths all right working
so far okay back on track so the
arithmetic just stops adding up at a
certain point and so this big number
problem is actually what inspired this
talk and now we're gonna get into
Beyonce I promise show you've all been
waiting with bated breath so at work so
for a bit of context at jackster we're
building a massive database of music
credits so you can look up your favorite
song and see who wrote produced recorded
whatever and you can see all their names
and click through whatever so work one
day I was working on a page let's say I
was looking at drunk in love by Beyonce
which happens to be one of my favorite
karaoke songs make it happen also in
case you didn't understand the reference
of my shirt because you weren't familiar
with Beyonce's discography this is the
reference okay so this is the page for
drunken love by the USA on Jack's toe
but you might notice something a bit
weird in that credits panel on the left
is that Beyonce is both the featured
artist and the main artist which is
not really true because jay-z's the
featured artist on that song I mean to
me this is a feature more than a bug but
double Beyonce hell yeah cool so I
noticed that we had this duplicate Dada
rendering on the page and Beyonce
wouldn't like this right she'd probably
want jay-z to be represented fairly so I
checked the API response and I saw that
yeah we've got beyond saying we've got
jay-z there's those two things are
coming through but having a look at
those IDs if you notice the last few
digits that's not unique which is not
ideal because they're clearly not the
same object and so the problem here is
that when we take the original IDs which
ended in 167 and 168 JavaScript was
passing them in correctly when I got
them because those numbers were too
large and so what was happening because
we were getting the same IDs the
framework that I use is embo and Amba
Dada was saying hey I've already got a
resource object with that ID I'm not
gonna fetch it again so here have
beyonce again she's again feature or not
a bug
but my boss didn't think so yeah so as
you can see if you have IDs without
numeric and they are incrementing and
they're too large probably gonna run
into problems like this and you probably
gonna stare you screen for like three
hours going why maybe right and so we
were getting chiefly katana on the page
which was not ideal something to look
out for when you are handling really big
numbers in API responses is that
sometimes they'll be a difference
between like when you open your response
in a new tab versus in dev tools so when
I was looking in dev tools the IDs were
exactly the same so they were passed
already
where is when I opened the response up
in a new tab it was the original
i D that was one six seven and one six
eight so that's not ideal that's
happening in Chrome and Safari so you
get the correct unpassed integer in a
new tab but the past integer and dev
tools in Firefox you get the past
integer in both the new tab and the dev
tools
who knows although in edge now that it's
chromium you'll probably get the same
behavior as Chrome so that's cool I
don't really understand why that's
happening if anyone works on these kind
of tools and can enlighten me I would
love to know why it's like different in
a new tab versus in the dev tools yeah
so because we had the incremental
numeric IDs it was a problem so our
solution was to move to you IDs which is
a pretty common solution they solve a
bunch of problems for us that was
primarily this problem where numbers
were too large and the funny thing was
we were actually using you IDs unlike
every other table we just forgotten this
one in the database and that was like
and so because we fixed that now drunken
love appears with the correct credits
for jay-z and Beyonce and the king and
queen are happy so this just in well
like a year ago but this just in we also
have now big int which is a new numeric
primitive that was introduced about
twelve months ago like a week before the
first time I gave this talk and I was
like oh my god so stressful so it is
available in Chrome Firefox 68 Vita and
edge it became available in Firefox 68
beta like a week ago which was super
exciting if your numbers nerd like me
and it means we can represent numbers
beyond that maximum safe integer which
is pretty exciting
so we can create them by appending
in to a number so we type in 100 N and
we receive back 100 N which is a big int
you can also use the big int method with
a string or a number we can't use any
floats because it is an integer not the
float or not big int not big decimal we
can do arithmetic with other big in
switch is cool we can do adding
subtracting multiplying we can divide
but because we won't return any decimals
it will just round to 0 so 10 divided by
3 is 3 and 1/3 but it'll just say 3 we
can do this operation I don't know what
it's called but it's like when you do
something to the power of let's call it
^ and we can also do modulo which is
cool we can't do mixed type operations
so we can't add 100 into 100 they're
different numeric types so we can't
actually mix them but we can compare
them so they have loose can loose
equality to regular numbers and we can
compare them like with greater than and
less then they'll compare correctly so
if we have like a array of mixed types
we can sort them things like that um now
let's do some maths like some real maths
with these big numbers so earlier we had
this problem where we were adding to the
maximum safe integer and everything was
just really confusing and weird let's
try that with big num Oh big integer so
I'll set a variable big num and then
I'll add 1 all right cool it works
it works yeah clap for the creators of
bigot it just keeps going it's so
beautiful I love it I love it yeah so
big in is not yet ready for production
apps it's not available in all browsers
and there's not a huge amount of
documentation available but um this is
how I feel about it
big numbers cool what I think is most
exciting about this is that this problem
didn't even exist when JavaScript was
created like what 23 24 years ago
I mean javascript is kind of still like
a baby in terms of what it can do but
like some babies grow up to be Beyonce
so maybe JavaScript will grow up to be
Beyonce but I think it's really cool
that you know it's easy to get caught up
in JavaScript fatigue sometimes but I
think it's really cool to be working in
an ecosystem that is constantly evolving
and growing and loading and fixing its
mistakes which is cool so to summarize
javascript has some really weird number
quirks but when you kind of dig into
them they're not totally unreasonable I
would say they are totally reasonable
when you kind of know what's going on so
something to kind of just be aware of I
guess when you're talking about precise
numbers remember that javascript uses 64
bit floating points so there are going
to be precision errors when you're going
any further than 17 decimal places so
around things and when we're talking
about really big numbers remember that
there's that maximum safe integer try
not to go beyond it if you can I'll have
your IDs passed through with strings or
different kind of types and remember
that big ant is coming which is really
cool I'm excited so I'm hoping that
after this talk with mass you'll be a
little less confused like this good boy
or a little less confused be and a
little more slay thank you so much
[Applause]