Question

I'm writing a program that calculates the nth position of the Fibonacci Sequence. The minimum end goal of the program is to be able to print the 100th, the ideal end goal is to calculate beyond that point. For this reason I have to use primitive type long to deal with how large the numbers are.

    public static long fibonacci (long n)
    {
    double phi = ((1 + Math.sqrt(5))/2);
    double result;
    result = ((Math.pow(phi, n))/Math.sqrt(5));

    return (long) result;
    }

This takes a number called Phi, to the power of the position I want to find. Then that value is divided by the square root of 5. Now the 100th Fibonacci Number is 354224848179262000000 I can successfully get this number but due to doubles not being able to handle large numbers it's compressed into Scientific Notation. (Or at least I assume that's why it's in Scientific Notation)

So my thought process is, by casting it to a long, a variable type that can manage larger numbers it would print it as the whole, "354224848179262000000", not "3.542248481792631E20." So I successfully casted to a long and return the result and this is where the problem comes in. (Sorry for having so much background information to go through)

When I cast the decimal, which is the correct answer, it converts the number into something completely different. The number I get is 9223372036854775807. So can someone explain what I did wrong, or what I need to do to get, "3.542248481792631E20" to print out as, "354224848179262000000" Thanks everyone!

Here is the entirety of my code, hopefully you guys can spot something or explain something to me. Maybe I am misunderstanding how longs function.

import java.util.Scanner;

public class FibLong
{

    public static void main(String[] args) 
    {
        long position;
        long answer;
        Scanner input = new Scanner (System.in);
        System.out.print ("Please enter an Nth position within the Fibonacci sequence: ");
        position = input.nextLong();
        answer = fibonacci(position);
        System.out.printf ("The Fibonacci number of position " + position + " is the number " + answer);
    }

    public static long fibonacci (long n)
    {
        double phi = ((1 + Math.sqrt(5))/2);
        double result;
        result = ((Math.pow(phi, n))/Math.sqrt(5));
        return (long) result;
    }

}
Was it helpful?

Solution

When downcasting a double value that is too large to fit in a long, this is the expected behavior. The value that results is in fact Long.MAX_VALUE.

To retain precision, consider converting it to a BigInteger or BigDecimal instead.

The JLS, Section 5.1.3, covers this "narrowing primitive conversion".

A narrowing conversion of a floating-point number to an integral type T takes two steps:

  1. In the first step, the floating-point number is converted either to a long, if T is long, or to an int, if T is byte, short, char, or int, as follows:

    • If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0.

    • Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:

a. If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.

b. Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.

  • Otherwise, one of the following two cases must be true:

a. The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is the smallest representable value of type int or long.

b. The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or long.

(my emphasis)

OTHER TIPS

Don't use double for numbers of this size, because the double values are too far apart. So even if you convert your double to a BigDecimal or a BigInteger, your answer is very likely to be incorrect.

You will find some relevant information in this question. Unfortunately, BigDecimal doesn't have square roots built in. If I had to do this, I would work out sqrt(5) to the desired accuracy separately, do the required arithmetic in surd form, and substitute in sqrt(5) at the end.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top