Lädt...


🔧 Fibonacci, Integer overflow, memoization e um exagero


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

Vamos fazer um exercício.
Abaixo deixo um código que retorna o número na posição n da sequência de Fibonacci:

public static int fib(int n){
   if (n <= 1){
     return n;
   }
   return fib(n-1) + fib(n-2);
}

Que tal tentarmos mostrar no nosso terminal todos os números da sequência de fibonacci menores que 2147483647?

    public static int fib(int n){
       if (n <= 1){
           return n;
       }
       return fib(n-1) + fib(n-2);
    }

    public static void main(String[] args) {
        int position = 1;
        int currentNumber = fib(position);

        while (currentNumber < 2147483647) {
            System.out.println(currentNumber);
            position++;
            currentNumber = fib(position);
        }
    }

Os problemas

Ao executar o código, você vai perceber dois problemas principais:

  • Nosso loop nunca termina, e, estranhamente, números negativos passam a aparecer no console.
    Saída do console mostrando números negativos

  • O código fica cada vez mais lento conforme o tempo passa.

Mostrando que chega um momento em que levam 40 segundos pra calcular 1 número

Problema 1: Os números negativos

Ignora por um momento toda essa história de fibonacci e olhe esse código.

public static void main(String[] args) {
   int a = 2_000_000_000;
   int b = 2_000_000_000;
   System.out.println(a + b);
}

Quanto você acha que vai ser o resultado disso? 2 bilhões + 2 bilhões = 4 bilhões certo? Então no nosso código o resultado vai ser 4 bilhões... certo?

ERRADO!

A saída na verdade foi essa:

Saída do console mostrando -294967296

O motivo para esse resultado é o overflow. O tipo int tem um limite máximo de 2147483647 (ou 2^31 - 1). Quando esse limite é ultrapassado, o valor "retorna" ao menor valor possível do tipo int, que é -2147483648.

Por que nosso loop não parou?

Nosso loop deveria parar quando chegássemos a um número maior ou igual a 2147483647, mas como os valores de Fibonacci ultrapassaram o limite de int, números negativos começaram a ser gerados. Como nunca chegamos a um número maior que 2147483647, o loop nunca parou.

Solução para o problema 1

Pra manter as coisas simples, eu apenas mudarei o tipo de retorno da nossa função fib de int pra long que tem um limite muito maior. Nosso código ficará assim:

    public static long fib(long n){
       if (n <= 1){
           return n;
       }
       return fib(n-1) + fib(n-2);
    }

    public static void main(String[] args) {
        long position = 1;
        long currentNumber = fib(position);

        while (currentNumber < 2147483647) {
            System.out.println(currentNumber);
            position++;
            currentNumber = fib(position);
        }
    }

Agora, com o tipo long, conseguimos imprimir corretamente os números do Fibonacci até o maior número menor que 2147483647.

Saída do terminal mostrando todos números da sequencia de fibonacci até chegar a 1836311903

Resolvendo o problema 2: lentidão

Já percebeu uma coisa? Toda iteração do nosso loop a função fib recalcula todos os números anteriores da sequência. Ou seja, estamos repetindo cálculos desnecessários.

Como evitar recálculos desnecessários? Apresento-lhes: Memoization. A técnica de memoization é uma forma de guardar resultados já calculados para não passar novamente pelo processo de cálculo.

Vamos implementar um HashMap para guardar os valores já encontrados, onde a chave será a posição e o valor é o próprio número.


    static HashMap<Long, Long> memo = new HashMap<>();

    public static long fib(long n) {
        if (memo.containsKey(n)) {
            return memo.get(n);
        }
        if (n <= 1) {
            return n;
        }
        long result = fib(n - 1) + fib(n - 2);
        memo.put(n, result);
        return result;
    }

    public static void main(String[] args) {
        long position = 1;
        long currentNumber = fib(position);

        while (currentNumber < 2147483647) {
            System.out.println(currentNumber);
            position++;
            currentNumber = fib(position);
        }
    }

Lindo! Agora nosso código roda muuito mais rápido e resolvemos nosso problema.

O exagero

Na verdade, memoization não era necessário aqui. Eu só quis trazer para ensinar esse conceito. Nós podíamos simplesmente calcular cada número do Fibonacci até acabarmos nossa condição dessa forma:

    public static void main(String[] args) {
        long prev1 = 0;
        long prev2 = 1;
        long current;

        System.out.println(prev1);

        while (prev2 < 2147483647) {
            System.out.println(prev2);
            current = prev1 + prev2;
            prev1 = prev2;
            prev2 = current;
        }
    }

Acabei com a graça né? Desculpa! Mas pelo menos tu aprendeu algo novo.

Capa do artigo por: Gerd Altmann do Pixabay

...

🔧 Fibonacci, Integer overflow, memoization e um exagero


📈 95.87 Punkte
🔧 Programmierung

🔧 Implementing the Fibonacci Sequence in JavaScript: Common Approaches and Variations


📈 24.37 Punkte
🔧 Programmierung

🔧 First Blog Post - Fibonacci Sequence


📈 24.37 Punkte
🔧 Programmierung

🔧 The Fibonacci Algorithm In Javascript


📈 24.37 Punkte
🔧 Programmierung

🔧 The Fibonacci Algorithm In Javascript


📈 24.37 Punkte
🔧 Programmierung

🔧 How Far Can You Optimize a Program to Compute the Fibonacci Sequence?


📈 24.37 Punkte
🔧 Programmierung

🔧 Fibonacci Series - Coding Interview Question | Easy visual explanation


📈 24.37 Punkte
🔧 Programmierung

🔧 The Importance of Fibonacci in Machine Learning and Data Science


📈 24.37 Punkte
🔧 Programmierung

🔧 Finding Fibonacci Numbers Using Dynamic Programming


📈 24.37 Punkte
🔧 Programmierung

🔧 Learn C Programming: Fibonacci Series Generation


📈 24.37 Punkte
🔧 Programmierung

🔧 Case Study: Computing Fibonacci Numbers


📈 24.37 Punkte
🔧 Programmierung

🐧 Bash Shell Script to Display Fibonacci Series


📈 24.37 Punkte
🐧 Linux Tipps

🔧 Demystifying Dynamic Programming: From Fibonacci to Load Balancing and Real-World Applications


📈 24.37 Punkte
🔧 Programmierung

🎥 Fibonacci, MOTW, TypoSquatting, 486, CompSci AI, Ventura Bugfixes, & CISA Warnings - SWN #250


📈 24.37 Punkte
🎥 IT Security Video

🎥 Typosquatting | Mark of the Web | Fibonacci Lasers | CISA | & Apple – SWN250


📈 24.37 Punkte
🎥 IT Security Video

🐧 You know what? Now you can get numbers from Fibonacci sequence directly from Linux kernel!


📈 24.37 Punkte
🐧 Linux Tipps

🔧 Fibonacci Pyramid Partner Workout: Build Strength and Creativity for Better Software Engineering


📈 24.37 Punkte
🔧 Programmierung

🔧 Implementando Fibonacci: De O(2^N) a O(1)


📈 24.37 Punkte
🔧 Programmierung

🕵️ CVE-2000-1219 | GNU gcc 3.3.3 Integer Overflow -ftrapv integer coercion (ID 540517)


📈 22.1 Punkte
🕵️ Sicherheitslücken

🕵️ Tianocore EDK II Integer Truncation integer overflow [CVE-2019-14563]


📈 22.1 Punkte
🕵️ Sicherheitslücken

🕵️ FreeRDP up to 2.0.0 USB Redirection Integer integer overflow


📈 22.1 Punkte
🕵️ Sicherheitslücken

🕵️ SQLite up to 3.32.0 printf.c sqlite3_str_vappendf Integer integer overflow


📈 22.1 Punkte
🕵️ Sicherheitslücken

🕵️ Google Android up to 9 libexif Integer Integer Overflow memory corruption


📈 22.1 Punkte
🕵️ Sicherheitslücken

🕵️ Adobe Acrobat Reader Integer Integer Overflow memory corruption


📈 22.1 Punkte
🕵️ Sicherheitslücken

🕵️ Google Android NVIDIA TLZ TrustZone Integer Integer Overflow memory corruption


📈 22.1 Punkte
🕵️ Sicherheitslücken

🕵️ Google Android NVIDIA TLZ TrustZone Integer Integer Overflow Pufferüberlauf


📈 22.1 Punkte
🕵️ Sicherheitslücken

🔧 Optimize React Component Performance with Memoization Using React.memo()


📈 19.74 Punkte
🔧 Programmierung

🔧 Optimizing React Component Performance with Memoization and React.memo


📈 19.74 Punkte
🔧 Programmierung

🔧 What is memoization


📈 19.74 Punkte
🔧 Programmierung

🔧 Lazy loading and Memoization | ReactJS | Part 1


📈 19.74 Punkte
🔧 Programmierung

🔧 Understanding ReactJS re-renders and memoization


📈 19.74 Punkte
🔧 Programmierung

🔧 Optimizing React Performance with Redux and memoization


📈 19.74 Punkte
🔧 Programmierung

🔧 Weak memoization in Javascript


📈 19.74 Punkte
🔧 Programmierung

matomo