Bisecting Floating Point Numbers

Similar documents
An interesting related problem is Buffon s Needle which was first proposed in the mid-1700 s.

Math 340 Fall 2014, Victor Matveev. Binary system, round-off errors, loss of significance, and double precision accuracy.

2 Computation with Floating-Point Numbers

Table : IEEE Single Format ± a a 2 a 3 :::a 8 b b 2 b 3 :::b 23 If exponent bitstring a :::a 8 is Then numerical value represented is ( ) 2 = (

MAT128A: Numerical Analysis Lecture Two: Finite Precision Arithmetic

Integers. N = sum (b i * 2 i ) where b i = 0 or 1. This is called unsigned binary representation. i = 31. i = 0

LECTURE 0: Introduction and Background

Design and Analysis of Algorithms Prof. Madhavan Mukund Chennai Mathematical Institute

What Every Programmer Should Know About Floating-Point Arithmetic

Reals 1. Floating-point numbers and their properties. Pitfalls of numeric computation. Horner's method. Bisection. Newton's method.

Variables and Data Representation

Lecture 6 Binary Search

Basics of Computational Geometry

Topic Notes: Bits and Bytes and Numbers

/633 Introduction to Algorithms Lecturer: Michael Dinitz Topic: Priority Queues / Heaps Date: 9/27/17

Graphics calculator instructions

Hi everyone. Starting this week I'm going to make a couple tweaks to how section is run. The first thing is that I'm going to go over all the slides

9.1 Bracketing and Bisection

(Refer Slide Time: 02:59)

Floating Point. CSE 351 Autumn Instructor: Justin Hsia

Floating-point representation

Introduction to Functional Programming: Lecture 7 2 Functions as innite data structures Ordinary ML data structures are always nite. We can, however,

Intro to Algorithms. Professor Kevin Gold

Divisibility Rules and Their Explanations

2 Computation with Floating-Point Numbers

1.00 Lecture 19. Numerical Methods: Root Finding

Floating Point Considerations

Floating Point (with contributions from Dr. Bin Ren, William & Mary Computer Science)

Week - 04 Lecture - 01 Merge Sort. (Refer Slide Time: 00:02)

9.1 Bracketing and Bisection

What Secret the Bisection Method Hides? by Namir Clement Shammas

Limits. f(x) and lim. g(x) g(x)

Scientific Computing. Error Analysis

Remember Java Data Types

Unit testing with pytest and nose 1

Matlab Basics Lecture 2. Juha Kuortti October 28, 2017

Classes of Real Numbers 1/2. The Real Line

Recursively Enumerable Languages, Turing Machines, and Decidability

CS429: Computer Organization and Architecture

Floating Point. CSE 351 Autumn Instructor: Justin Hsia

(Refer Slide Time 6:48)

Topic Notes: Bits and Bytes and Numbers

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Floating-point numbers. Phys 420/580 Lecture 6

Review of Calculus, cont d

Equations and Functions, Variables and Expressions

6.001 Notes: Section 15.1

n! = 1 * 2 * 3 * 4 * * (n-1) * n

Machine Computation of the Sine Function

Up next. Midterm. Today s lecture. To follow

Computer Architecture Chapter 3. Fall 2005 Department of Computer Science Kent State University

Expressions and Casting. Data Manipulation. Simple Program 11/5/2013

6.001 Notes: Section 6.1

AXIOMS FOR THE INTEGERS

10.4 Linear interpolation method Newton s method

Chapter 4. Number Theory. 4.1 Factors and multiples

Expressions and Casting

Numerical computing. How computers store real numbers and the problems that result

In the previous presentation, Erik Sintorn presented methods for practically constructing a DAG structure from a voxel data set.

Lecture 15: Segmentation (Edge Based, Hough Transform)

How to approach a computational problem

Floating Point. CSE 351 Autumn Instructor: Justin Hsia

Congruence Arithmetic

Chapter 2: Number Systems

Simple Data Types in C. Alan L. Cox

f( x ), or a solution to the equation f( x) 0. You are already familiar with ways of solving

C++ Data Types. 1 Simple C++ Data Types 2. 3 Numeric Types Integers (whole numbers) Decimal Numbers... 5

1.2 Round-off Errors and Computer Arithmetic

4.7 Approximate Integration

Lecture 1 Contracts : Principles of Imperative Computation (Fall 2018) Frank Pfenning

Contents. Hilary Term. Summary of Numerical Analysis for this term. Sources of error in numerical calculation. Solving Problems

Lecture 1 Contracts. 1 A Mysterious Program : Principles of Imperative Computation (Spring 2018) Frank Pfenning

/633 Introduction to Algorithms Lecturer: Michael Dinitz Topic: Sorting lower bound and Linear-time sorting Date: 9/19/17

2 Homework: Bond class, fair value, duration & yield

Math 5320, 3/28/18 Worksheet 26: Ruler and compass constructions. 1. Use your ruler and compass to construct a line perpendicular to the line below:

2. Periodic functions have a repeating pattern called a cycle. Some examples from real-life that have repeating patterns might include:

9. MATHEMATICIANS ARE FOND OF COLLECTIONS

Physics 306 Computing Lab 5: A Little Bit of This, A Little Bit of That

We will give examples for each of the following commonly used algorithm design techniques:

Slide Set 1. for ENEL 339 Fall 2014 Lecture Section 02. Steve Norman, PhD, PEng

2.3 Circular Functions of Real Numbers

We cover recursion in 150. Why do it again in 151?

1 Dynamic Memory continued: Memory Leaks

Induction and Semantics in Dafny

Basics of Computation. PHY 604:Computational Methods in Physics and Astrophysics II

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

Data Representation Floating Point

Graphics calculator instructions

Lecture #15 March 3, 2004 A Worked Problem in Floating Point

Introduction to Computer Programming in Python Dr. William C. Bulko. Data Types

A Prehistory of Arithmetic

Chapter 2. Data Representation in Computer Systems

Data Representation Type of Data Representation Integers Bits Unsigned 2 s Comp Excess 7 Excess 8

These are reserved words of the C language. For example int, float, if, else, for, while etc.

y= sin( x) y= cos( x)

introduction to Programming in C Department of Computer Science and Engineering Lecture No. #40 Recursion Linear Recursion

perform. If more storage is required, more can be added without having to modify the processor (provided that the extra memory is still addressable).

Lecture Transcript While and Do While Statements in C++

CS 261 Fall Floating-Point Numbers. Mike Lam, Professor.

Creating a new data type

Transcription:

Squishy Thinking by Jason Merrill jason@squishythinking.com Bisecting Floating Point Numbers 22 Feb 2014 Bisection is about the simplest algorithm there is for isolating a root of a continuous function: 1. Start with an interval such that the function takes on oppositely signed values on the points. 2. Split the interval at its midpoint. 3. Recurse into whichever half has points on which the function takes on oppositely signed values. After each step, the new interval is half as large as the previous interval and still contains at least one zero (by the Intermediate Value Theorem). I want to highlight a couple of interesting issues that arise when implementing bisection in oating point arithmetic that you might miss if you just looked at the de nition of the algorithm. In Julia code, a single step of bisection looks like this: Julia treats oating point arithmetic the same way all modern programming environments do: according to the IEEE 754 standard. The examples here are in Julia 1 of 11 01/16/2016 03:28 PM

because I plan to talk more about the language in the future, but everything in this post could as easily be written in any other language. function bisect_step(fn, x1, x2) xm = (x1 + x2)/2 # Return the sub-interval with # oppositely-signed points if sign(fn(x1))!= sign(fn(xm)) return x1, xm else return xm, x2 For example, 2 of 11 01/16/2016 03:28 PM

julia> x1, x2 = bisect_step(sin, 2.0, 4.0 (3.0,4.0) julia> x1, x2 = bisect_step(sin, x1, x2) (3.0,3.5) julia> x1, x2 = bisect_step(sin, x1, x2) (3.0,3.25) julia> x1, x2 = bisect_step(sin, x1, x2) (3.125,3.25) julia> x1, x2 = bisect_step(sin, x1, x2) (3.125,3.1875) The rst interesting question when implementing bisection is when should I stop bisecting? In pure mathematics, you can think of carrying the process on inde nitely, but a computer program should halt. Here s a little puzzle. I claim that one of the following functions always halts, and the other can loop forever. The functions differ only in their stopping criteria. Which one is which? function bisect1(fn, x1, x2) @assert sign(fn(x1))!= sign(fn(x2)) tol = 1e-13 # Stop when function values are below # a set tolerance while abs(fn(x1)) > tol abs(fn(x2)) x1, x2 = bisect_step(x1, x2, fn) return x1, x2 function bisect2(fn, x1, x2) 3 of 11 01/16/2016 03:28 PM

@assert sign(fn(x1))!= sign(fn(x2)) # Stop when the mean of the points # is equal to one of the points while x1 < (x1 + x2)/2 < x2 x1, x2 = bisect_step(x1, x2, fn) return x1, x2 Let s try them out: julia> bisect1(x -> 1000*sin(x), 2.0, 4.0 # loops forever... julia> bisect2(x -> 1000*sin(x), 2.0, 4.0 (3.141592653589793,3.1415926535897936) This is the opposite of what would have happened if we ran these algorithms using mathematical real numbers instead of computer oating point numbers. Over the reals, the rst algorithm terminates for continuous functions by the de nition of continuity, and the second algorithm doesn t terminate because for any two non-equal real numbers x 1 < x 2 it s always true that x 1 < (x 1 + x 2)/2 < x 2. Over oating point doubles, the rst algorithm doesn t terminate because there is no oating point number 2.0 < x < 4.0 such that 13 1000sin (x) < 10, and the second algorithm does terminate because for any nite oating point number x 1 (except the largest nite oat), 4 of 11 01/16/2016 03:28 PM

there exists a strictly larger oating point number x 2 such that (x 1 + x 2)/2 = x 1 or (x 1 + x 2)/2 = x 2. Both of these results might be surprising if you aren t familiar with the details of oating point numbers. They arise due to the granularity of oats. There is a nite gap between any oat and the next largest oat. The size of the gap deps (proportionally) on the size of the number. In Julia, you can nd the size of the gap using eps: julia> eps(1.0) 2.220446049250313e-16 If x 1 is a oat and x 2 is the next largest oat, it is always true that their mean is either x 1 or x 2, because there are no other values between them. For example, julia> let x=3.0, y=x+eps(x) (x + y)/2 3.0 The oating point representation of π is julia> fpi = convert(float64, pi) 3.141592653589793 Its sine is positive: 5 of 11 01/16/2016 03:28 PM

julia> sin(fpi) 1.2246467991473532e-16 The next largest oating point number is julia> fpi_plus = fpi + eps(fpi) 3.1415926535897936 and its sine is negative: julia> fpi_plus = fpi + eps(fpi) -3.216245299353273e-16 16 Neither of these outputs is within 10 of 0.0, which is why bisect1 fails to terminate. On the other hand, bisect2 managed to nd exactly these inputs as lower and upper bounds of a root of sin. It didn t need any explicit tolerances at all. In this sense, bisect2 is an exemplary oating point algorithm. The answer to our present question, when should I stop bisecting?, is when there are no more oating point numbers between your lower and upper bound, whenever this is practical. Checking whether the mean of the points is equal to one of the points is a convenient way to check this condition. Choosing a different arbitrary tolerance in a general purpose oating point algorithm is impolite. Absolute tolerances like the 1e-13 in bisect1 are inappropriate in general purpose 6 of 11 01/16/2016 03:28 PM

algorithms because oating point numbers don t come with units attached, so an algorithm with an absolute tolerance will behave differently deping on whether your user measures, e.g., lengths in millimeters or meters. Relative tolerances are better but fail when the answer is supposed to be 0.0. The spacing between oating point numbers cleanly elides these two limits, being relative for nite numbers, and nite for 0.0. If you write your algorithms to compute to full precision, you save your users from having to think about tolerance conventions speci c to your library. It can be tempting to think of oating point numbers as broken real numbers, but it s much more productive to think of oating point numbers as a carefully thought out set of conventions for rounding the output of one algorithm to be appropriate as an input to another algorithm. Floating point numbers help with the hard work of making our programs composable. Now that we know when to stop bisecting, the next interesting question is how many iterations will it take to bisect a root to full precision? As we ve just discussed, oating point numbers are a 64 nite set. There are 2 oating point doubles (actually somewhat less because a whole group of them are NaN). Each step of bisection should halve the number of oats contained in the interval. This means it should always take less than 64 steps to reach full precision. Let s see some examples: 7 of 11 01/16/2016 03:28 PM

function count_bisect2_steps(fn, x1, x2) i=0 while x1 < (x1 + x2)/2 < x2 x1, x2 = bisect_step(fn, x1, x2) i += 1 return i # Isolate root at pi julia> count_bisect2_steps(sin, 3.0, 4.0) 51 # good # Isolate root at 0.0 julia> count_bisect2_steps(sin, -1.0, 1.0 1075 # bad What happened? Earlier, I said each step of bisection should halve the number of oats contained in the interval, but as written, bisect_step doesn t actually do this. The problem is that oats aren t evenly distributed. They are much denser near 0.0 than far from it. This means that bisecting toward a root at 0.0 using the arithmetic mean eliminates fewer than half of the oats in the interval at each step. Instead of bisecting the values of oating point numbers, what we really want to do is bisect a function that counts them. That would make it easy to eliminate exactly half of them at each step. Conveniently, the underlying binary representation of oating point numbers is 8 of 11 01/16/2016 03:28 PM

exactly a function that counts them. If we reinterpret the binary representation of a oat as an integer, we can nd the mean of the two integers that represent the points, instead of the mean of the values of the two points. Here s a function that does just that: function _middle(x1::float64, x2::float64 # Use the usual float rules for combini # non-finite numbers if!isfinite(x1)!isfinite(x2) return x1 + x2 # Always return 0.0 when inputs have op if sign(x1)!= sign(x2) && x1!= 0.0 && return 0.0 negate = x1 < 0.0 x2 < 0.0 x1_int = reinterpret(uint64, abs(x1)) x2_int = reinterpret(uint64, abs(x2)) unsigned = reinterpret(float64, (x1_int return negate? -unsigned : unsigned There are some minor complications for negative numbers. The wikipedia page on the oating point standard has more information on exactly how the binary encoding of oats works. I also recomm What every computer scientist should know about oating point numbers. In 9 of 11 01/16/2016 03:28 PM

_middle, I avoid these complications by returning 0.0 for intervals with one negative point and one positive point, and by casting negative intervals to positive intervals and back. The >> 1 is right shift, a fast way to divide integers by 2. Using this function, we can de ne our nal version of bisect_root: function bisect_root(fn, x1, x2) xm = _middle(x1, x2) s1 = sign(fn(x1)) s2 = sign(fn(x2)) while x1 < xm < x2 sm = sign(fn(xm)) if s1!= sm x2 = xm s2 = sm else x1 = xm s1 = sm xm = _middle(x1, x2) return x1, x2 This version also inlines bisect_step in a way that avoids unnecessary reevaluations of the function. It has the nice property that it will 10 of 11 01/16/2016 03:28 PM

always converge to full precision in 65 function evaluations or fewer (two initial evaluations, and one more per step for up to 63 additional steps). There are root bracketing algorithms that converge to full precision in fewer function evaluations for smooth functions (e.g. Brent s method), but well-implemented bisection has the advantages of simplicity (fewer places for bugs to hide), and very low overhead, because there is so little arithmetic aside from the objective function evaluations. I recently worked with John Verzani to get code very much like this nal version of bisect_root into the Roots.jl package. As of this writing, the pull request is currently awaiting review. 11 of 11 01/16/2016 03:28 PM