Die Geschichte eines arithmetischen Überlaufs, der in Ruby nicht auftreten sollte

Einführung

Der Autor, der hauptsächlich Ruby verwendet, ist auf einen arithmetischen Überlauf gestoßen und hat Lehren gezogen. Daher werde ich die aufgetretenen Situationen und Gegenmaßnahmen erläutern. ** * Diesmal gibt es kein mathematisches Problem ... **

Und danke für die große Auswahl an Tribonatch und Kommentaren! Unter ihnen möchte ich einen Artikel von @torifukukaiou vorstellen, der Tribonacci mit der Elixir-Version gelöst hat. [Ich habe versucht, das Tribonacci-Sequenzproblem mit Elixir zu lösen (Zeitlimit 10 Minuten)] (https://qiita.com/torifukukaiou/items/d5a6639edf541539ac3a?utm_campaign=email&utm_content=link&utm_medium=email&utm_source=public_mention)

Was hast du versucht zu tun?

Seit dem letzten Kampf mit der Tribonacci-Sequenz sind einige Tage vergangen, und ich suchte nach einer Möglichkeit, die Implementierung zu beschleunigen, um in Zukunft noch intensivere mathematische Probleme zu lösen. In der Zwischenzeit habe ich gelernt, dass die C-Sprache mit gem'RubyInline 'verwendet werden kann, und als ich sie implementiert habe, um die C-Sprache ein wenig zu berühren, ist ein arithmetischer Überlauffehler aufgetreten.

Über den Durchfluss bis zum Auftreten eines arithmetischen Überlaufs

Ich habe mit dem folgenden Befehl ein Verzeichnis und eine rb-Datei erstellt, VSCode geöffnet und bearbeitet.

$ cd Desktop
$ mkdir Ruby_with_c
$ cd Ruby_with_c
$ touch tribonacci.rb
$ bundle init
$ code .

Schreiben Sie gem'RubyInline ',' ~> 3.12 ','> = 3.12.4 'in Gemfile und bündeln Sie die Installation

Gemfile


# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

# gem "rails"
gem 'RubyInline', '~> 3.12', '>= 3.12.4'
$ bundle install

Kakikaki-Code ... (Wie schreibt man C-Sprache ... ´ · ௰ · `) ← Was hast du gemacht? (゚ Д ゚) Ich habe es geschrieben, weil es vorerst einfach sein kann! !!

tribonacci.rb


require 'inline'

class Tribonacci
  inline do |builder|
    builder.c "
      int add(int a, int b, int c){
        int d,i = 3;
        while (i<50){
          d = a + b + c;
          a = b;
          b = c;
          c = d;
          i++;
        }
        return c;
      }
    "
  end
end

puts Tribonacci.new.add(1,3,7)

Der obige Code ist der gleiche wie der Code, der implementiert wurde, um die Tribonatch-Sequenz in Ruby zu lösen. Bei Implementierung mit diesem Code tritt jedoch ein ** arithmetischer Überlauf auf und das Berechnungsergebnis ist negativ **.

Kommentar

Durch Schreiben von require'inline in die erste Zeile können Sie externen Code (C-Sprache) in den Ruby-Code schreiben. Die int-Beschreibung in der 6. Zeile definiert den Datentyp vom Typ int für jeden. Damit erscheint jedoch ein abnormaler Wert, der als Minus angezeigt wird, aus der 36. Antwort in der Tribonacci-Sequenz.

  1. Antwort 1831177831
  2. Antwort-926906165

Dieses Phänomen wird als ** arithmetischer Überlauf ** bezeichnet. In der Sprache C wird das Verarbeitungssystem, das zum Minimalwert LONG_MIN (-2147483648) wird, wenn der Maximalwert von int, INT_MAX (2147483647), um 1 überschritten wird. In dieser Implementierung scheint das 36. Element INT_MAX (2147483647) überschritten und von -2147483648 gestartet zu haben.

Dieses Mal wechseln wir von int zu long, um einen arithmetischen Überlauf zu verhindern. langer Maximalwert: 9223372036854775807

tribonacci.rb


require 'inline'

class Tribonacci
  inline do |builder|
    builder.c "
      long add(long a, long b, long c){
        long d,i = 3;
        while (i<50){
          d = a + b + c;
          a = b;
          b = c;
          c = d;
          i++;
        }
        return c;
      }
    "
  end
end

puts Tribonacci.new.add(1,3,7)

Durch den Wechsel zu lang kommt der 36. 3368061131 heraus. Ruby-Ganzzahlen werden übrigens automatisch um die Anzahl der Stellen erweitert, sodass kein arithmetischer Überlauf auftritt. Wenn ich also nur Ruby berühren würde, würde ich keinen arithmetischen Überlauf feststellen. Vielen Dank für das Treffen! !!

abschließend

Nachdem ich eine Weile die C-Sprache berührt hatte, stieß ich auf einen Fehler, den ich in Ruby nicht gefunden hatte, und lernte viel. Derzeit konnte ich nur das Juwel 'RubyInline' einführen, aber in Zukunft möchte ich eine Erweiterungsbibliothek für die Sprache C erstellen und eine Hochgeschwindigkeitsverarbeitung implementieren, um intensive mathematische Probleme zu lösen.

Bonus

Wenn jemand ein interessantes mathematisches Problem hat, hinterlasse es bitte in den Kommentaren! !! Der Lösungsprozess war sehr lehrreich und ich war süchtig nach mathematischen Problemen. Basierend auf dem Geist, die Punkte zu verbinden, werde ich weiterhin mein Bestes geben und glaube, dass die Tage des Eintauchens eines Tages leuchten werden!

Recommended Posts

Die Geschichte eines arithmetischen Überlaufs, der in Ruby nicht auftreten sollte
Eine Geschichte über das Konvertieren von Zeichencodes von UTF-8 in Shift-jis in Ruby
Eine Geschichte über das JDK in der Java 11-Ära
Eine sehr nützliche Geschichte über Rubys Struct-Klasse
Eine Geschichte über das Erstellen eines Builders, der den Builder erbt
Eine Geschichte über einen Fehler während der Migration in Docker PHP Laravel
Ich habe einen Interpreter (Compiler?) Mit ungefähr 80 Zeilen in Ruby erstellt.
So ändern Sie eine Zeichenfolge in einem Array in eine Zahl in Ruby
Eine Geschichte über eine BeanNotOfRequiredTypeException, die nach der Anwendung von AOP im Frühjahr aufgetreten ist
[Docker] Eine Geschichte über einen Fehler beim Erstellen von Docker
Eine Geschichte, die ein Ruby-Anfänger gemacht und einen LINE BOT veröffentlicht hat, der die Zugzeit in 2 Monaten erzählt
Multiplikation innerhalb eines Ruby-Arrays
Über reguläre Ausdrücke in Ruby
Die Geschichte, dass Tomcat in Eclipse unter einem Timeout-Fehler litt
Eine Geschichte über das Schreiben einer Verhältnisberechnung in einer internen Lernsitzung
Wenn Sie einen Anruf erhalten, senden Sie eine SMS an diese Nummer
Erstellen einer ArrayList, mit der Sie die Koordinaten einer zweidimensionalen Ebene eingeben und abrufen können