F# Program to Implement Exponential Search

F# Program to Implement Exponential Search

Searching efficiently in large datasets is a key skill for any programmer. While simple searches like Linear Search are easy to understand, they can be slow for big arrays. Exponential Search is an advanced technique that helps locate an element quickly in a sorted array by first finding a range where the element might exist and then applying Binary Search within that range. This makes it very fast, especially for large datasets where the element is closer to the beginning of the array.

Pluralsight Logo
Accelerate your tech career
with hands-on learning.
Whether you're a tech newbie or a total pro,
get the skills and confidence to land your next move.
Start 10-Day Free Trial

Exponential Search is beginner-friendly because it combines two simple ideas: doubling a search index to find a potential range, and then applying Binary Search to pinpoint the element. Learning Exponential Search helps beginners understand optimization strategies, recursion, and how combining algorithms can improve performance. It’s widely used in applications like searching in memory-limited systems, large databases, and even for real-time searches in sorted lists.

Program 1: Basic Exponential Search Using Loops

This program demonstrates how Exponential Search works iteratively. It doubles the search index until it finds a range and then performs a Binary Search within that range.

open System

let binarySearch (arr:int[]) key left right =

    let mutable l = left
    let mutable r = right
    let mutable foundIndex = -1

    // Stop loop naturally once foundIndex is set
    while l <= r && foundIndex = -1 do

        let mid = l + (r - l) / 2

        if arr.[mid] = key then
            foundIndex <- mid
        elif arr.[mid] < key then
            l <- mid + 1
        else
            r <- mid - 1

    foundIndex


let exponentialSearch (arr:int[]) key =

    if arr.Length = 0 then -1
    elif arr.[0] = key then 0
    else

        let mutable i = 1

        while i < arr.Length && arr.[i] <= key do
            i <- i * 2

        binarySearch arr key (i / 2) (min i (arr.Length - 1))


[<EntryPoint>]
let main argv =

    let numbers = [| 1; 3; 5; 7; 9; 11; 13; 15 |]
    let key = 11
    let result = exponentialSearch numbers key

    if result <> -1 then
        printfn "Element %d found at index %d" key result
    else
        printfn "Element %d not found" key

    0

Here, the search index doubles until it finds a value larger than the key. Then Binary Search is used in the reduced range. This approach reduces comparisons for large arrays and is very efficient for elements closer to the beginning. Beginners can easily follow how the range is identified before the precise search.

Program 2: Recursive Exponential Search

Recursion makes Exponential Search easier to visualize as each doubling step can be a separate function call.

open System

let rec binarySearchRec (arr:int[]) key left right =

    if left > right then -1

    else
        let mid = left + (right - left) / 2
        if arr.[mid] = key then mid
        elif arr.[mid] < key then binarySearchRec arr key (mid + 1) right
        else binarySearchRec arr key left (mid - 1)


let rec exponentialSearchRec (arr:int[]) key i =

    if i >= arr.Length || arr.[i] > key then
        binarySearchRec arr key (i / 2) (min i (arr.Length - 1))

    else exponentialSearchRec arr key (i * 2)


[<EntryPoint>]
let main argv =

    let numbers = [| 2; 4; 6; 8; 10; 12; 14 |]
    let key = 10
    let result = 
        if numbers.[0] = key then 0
        else exponentialSearchRec numbers key 1

    if result <> -1 then
        printfn "Element %d found at index %d" key result  
    else
        printfn "Element %d not found" key

    0

The recursive version helps beginners understand how the doubling and narrowing process works naturally. Each recursion step either doubles the index or calls Binary Search on a smaller range.

Program 3: Exponential Search with Negative and Positive Numbers

Exponential Search works with negative numbers as well as positive numbers, as long as the array is sorted.

open System

let exponentialSearchMixed (arr:int[]) key =

    if arr.Length = 0 then -1
    elif arr.[0] = key then 0
    else

        let mutable i = 1

        while i < arr.Length && arr.[i] <= key do
            i <- i * 2

        let rec binarySearchMixed left right =

            if left > right then -1
            else
                let mid = left + (right - left) / 2
                if arr.[mid] = key then mid
                elif arr.[mid] < key then binarySearchMixed (mid + 1) right
                else binarySearchMixed left (mid - 1)

        binarySearchMixed (i / 2) (min i (arr.Length - 1))


[<EntryPoint>]
let main argv =

    let numbers = [| -20; -10; 0; 5; 10; 15; 20 |]
    let key = -10
    let result = exponentialSearchMixed numbers key

    if result <> -1 then
        printfn "Element %d found at index %d" key result
    else
        printfn "Element %d not found" key

    0

By including negative numbers, beginners can practice real-world scenarios and learn that the doubling and binary search logic is the same regardless of number sign.

Program 4: Exponential Search Returning Option Type

Using option type in F# is more idiomatic and helps avoid using sentinel values like -1.

open System

let exponentialSearchOption (arr:int[]) key =

    let rec binarySearchOpt left right =

        if left > right then None
        else

            let mid = left + (right - left) / 2
            if arr.[mid] = key then Some mid
            elif arr.[mid] < key then binarySearchOpt (mid + 1) right
            else binarySearchOpt left (mid - 1)

    if arr.Length = 0 then None
    elif arr.[0] = key then Some 0
    else

        let mutable i = 1

        while i < arr.Length && arr.[i] <= key do
            i <- i * 2

        binarySearchOpt (i / 2) (min i (arr.Length - 1))


[<EntryPoint>]
let main argv =

    let numbers = [| 1; 3; 5; 7; 9; 11 |]
    let key = 7

    match exponentialSearchOption numbers key with
    | Some index -> printfn "Element %d found at index %d" key index
    | None -> printfn "Element %d not found" key

    0

Returning option makes the code safer and more readable, which is good practice for beginners learning F#.

Program 5: Step-by-Step Exponential Search

This program prints each step of the exponential growth and the binary search range, helping beginners visualize the process.

open System

let exponentialSearchStep (arr:int[]) key =

    if arr.Length = 0 then -1
    elif arr.[0] = key then 0
    else

        let mutable i = 1

        while i < arr.Length && arr.[i] <= key do
            printfn "Doubling index: %d" i
            i <- i * 2

        let left = i / 2
        let right = min i (arr.Length - 1)
        printfn "Binary search in range %d to %d" left right

        let mutable l = left
        let mutable r = right
        let mutable foundIndex = -1

        // Stop loop naturally when key is found
        while l <= r && foundIndex = -1 do

            let mid = l + (r - l) / 2
            printfn "Checking mid index %d" mid

            if arr.[mid] = key then
                foundIndex <- mid
            elif arr.[mid] < key then
                l <- mid + 1
            else
                r <- mid - 1

        foundIndex


[<EntryPoint>]
let main argv =

    let numbers = [| 1; 2; 4; 8; 16; 32 |]
    let key = 8
    let result = exponentialSearchStep numbers key

    if result <> -1 then
        printfn "Element %d found at index %d" key result
    else
        printfn "Element %d not found" key

    0

Printing the steps helps beginners understand how exponential growth identifies the search range and how Binary Search then locates the element efficiently.

Frequently Asked Questions (FAQ)

This section answers common beginner questions about Exponential Search.

Q1. What is Exponential Search?
Exponential Search finds a key in a sorted array by first finding a range where the key might exist using exponential index doubling, then applying Binary Search within that range.

Q2. Does the array need to be sorted?
Yes, Exponential Search requires a sorted array for correctness.

Q3. Can it handle negative numbers?
Yes, negative and positive numbers are supported as long as the array is sorted.

Q4. Why is it faster than Linear Search?
It quickly narrows down the potential range by doubling the index, reducing comparisons for large arrays.

Q5. When should I use Exponential Search?
It is useful for searching in large sorted arrays, especially when the target element is closer to the beginning.

Conclusion

Exponential Search is a powerful and efficient algorithm for sorted arrays that combines exponential range detection with Binary Search. Through multiple F# programs, we explored iterative and recursive approaches, handling negative numbers, returning option types, and visualizing each step.

For beginners, practicing Exponential Search builds understanding of combined algorithms, optimized searching, and safe result handling in F#. Experimenting with different datasets helps reinforce the concepts and prepares learners for more advanced search and optimization techniques.

Scroll to Top