[JAVA] Eine Geschichte über das Schreiben einer Verhältnisberechnung in einer internen Lernsitzung

Einführung

Ich denke, es gibt Situationen, in denen der Wert geändert wird, während das Verhältnis beibehalten wird, z. B. das Bild vergrößern / verkleinern. Diesmal habe ich unter der Annahme einer solchen Situation versucht, die folgenden Probleme zusammen mit jungen Mitarbeitern zu lösen. Übrigens, wenn Sie das Netz durchsuchen, wird die Antwort herauskommen, also habe ich die Netzsuche verboten.


Problem

  1. Ermitteln Sie das Verhältnis zweier ganzzahliger Werte x und y
  2. Finden Sie den vergrößerten / verkleinerten Wert mit dem größeren Wert von x und y als Maximalwert max.

Lösung 1: Ausschluss

Zunächst war es am einfachsten, das Verhältnis mit einer einfachen Teilungsmethode zu ermitteln.

Beispiel.


x = 100
y = 10
x / y = 10
x ist 10 mal y
Das heißt, x:y=10:1

Ich denke, es ist intuitiv und leicht zu verstehen, aber es hat den Nachteil, dass es an Genauigkeit verliert, wenn es durch diese Methode nicht teilbar ist.

Beispiel.


x = 100
y = 30
x / y = 3.3333...
Ist x ungefähr 3 mal y?

In diesem Fall sollte "x: y = 10: 3" in Ordnung sein, aber mit dem Verhältnis, das unter Verwendung einer einfachen Teilungsmethode erhalten wird, gibt es ein Problem, dass y nicht 150 wird, wenn max im folgenden Problem auf 500 gesetzt wird. Es wird auftreten. Ich denke, dass es eine Ameise ist, in Abhängigkeit von der Fehlertoleranz mit der Verarbeitung von Brüchen umzugehen.


Lösung 2: Maximales Engagement

Als nächstes stellte ich als vorbereitete Lösung eine Methode vor, um das Verhältnis zu ermitteln, indem x und y durch das maximale Versprechen dividiert werden.

Beispiel.


x = 100
y = 30
Maximales Engagement= 10
x : y = x /Maximales Engagement: y /Maximales Engagement
Das heißt, x:y=10:3

Mit dieser Methode können Sie das Verhältnis als Ganzzahl berechnen.


Euklidische Methode der gegenseitigen Teilung

Als Methode, um das maximale Engagement zu finden, "[Euklidische Methode der gegenseitigen Teilung](https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%BC%E3%82%AF%E3%83%" AA% E3% 83% 83% E3% 83% 89% E3% 81% AE% E4% BA% 92% E9% 99% A4% E6% B3% 95) ”.

Kurz zusammengefasst wird der folgende Vorgang wiederholt.

  1. Teilen Sie den großen Wert durch den kleinen Wert
  2. Wenn es einen Rest gibt, teilen Sie den ursprünglichen kleinen Wert durch den Rest, der herausgekommen ist.

Wiederholung und Schleife

Es gibt zwei Möglichkeiten, iterative Verarbeitung zu schreiben: rekursiv und Schleife. Die Aufklärung kann zu einem Stapelüberlauf führen, Sie können jedoch sauberen Code schreiben. Schleifen hingegen können redundanter Code sein und zu einer schlechten Sichtbarkeit führen, wenn die Bedingungen komplex werden. Beachten Sie auch, dass Sie in einer Endlosschleife enden, wenn Sie bei den Bedingungen für das Beenden beider Fehler einen Fehler machen.


Tail Call Optimierung

In modernen Sprachen kann ein rekursiver Stapelüberlauf durch Tail-Call-Optimierung behoben werden. Da es sich jedoch um eine Sprachfunktion (Compiler) handelt, wird keine Sprache gelöst. Berücksichtigen Sie dies daher bei der Implementierung.


In diesem Fall

Nur in Kotlin, aber [Fibonatch Count](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3% Ich habe versucht, mit 83% 83% E3% 83% 81% E6% 95% B0) zu bestätigen.

val x = 1836311903
val y = 1134903170

Das Obige ist die maximale maximale Anzahl von Fibonacci-Kombinationen, die von Int angegeben werden können, und selbst damit betrug die Anzahl der Versuche nur 45. Daher stellte sich in diesem Fall heraus, dass sowohl rekursive als auch Schleifen ohne besondere Aufmerksamkeit verwendet werden konnten.

Eine Wiederholung beim tatsächlichen Projektdenken ist jedoch eine Idee. Ist es für Teams mit unterschiedlichem Verständnis des Programms, vom jungen bis zum erfahrenen, nicht einfacher, Schleifen auf jeder Ebene in einer einfachen iterativen Verarbeitung wie diesem Problem zu verstehen? Es wurde beschlossen. Wenn es kompliziert wird, ist es natürlich schwierig, es selbst in einer Schleife zu verstehen. Daher müssen Möglichkeiten zur Verbesserung der Lesbarkeit, einschließlich der Wiederholung, in Betracht gezogen werden.


Codebeispiel

Der folgende Code schreibt dieses Problem neu, damit Sie leicht vergleichen können, was in jeder Sprache geschrieben wurde.


Kotlin

fun main(args: Array<String>) {
  val x = 30
  val y = 100
  val max = 500

  val gcdResult = gcd(x, y)
  val xRatio = x / gcdResult
  val yRatio = y / gcdResult
  println("Maximales Engagement: $gcdResult => $xRatio:$yRatio")
  
  val largeResult = max
  val smallResult = getSmallerGcdPair(x, y, largeResult)
  if(x > y) {
    println("$x:$y => $largeResult:$smallResult")
  } else {
    println("$x:$y => $smallResult:$largeResult")
  }
}

fun gcd(xInput: Int, yInput: Int): Int {
  var largeVal = Math.max(xInput, yInput)
  var smallVal = Math.min(xInput, yInput)
  var remVal = 0

  do{
    remVal = largeVal % smallVal
    largeVal = smallVal
    smallVal = remVal
  } while(remVal > 0)

  return largeVal
}

fun getSmallerGcdPair(xRatio: Int, yRatio: Int, largeResult: Int): Int {
  var largeRatio = Math.max(xRatio, yRatio)
  var smallRatio = Math.min(xRatio, yRatio)

  return largeResult / largeRatio * smallRatio    
}

Swift

func main() {
  let x: Int = 30
  let y: Int = 100
  let max = 500

  let gcdResult = gcd(x, y)
  let xRatio = x / gcdResult
  let yRatio = y / gcdResult
  print("Maximales Engagement: \(gcdResult) => \(xRatio) : \(yRatio)")

  let largeResult = max
  let smallResult = getSmallerGcdPair(xRatio, yRatio, largeResult)
  if(x > y) {
    print("\(x):\(y) => \(largeResult):\(smallResult)")
  } else {
    print("\(x):\(y) => \(smallResult):\(largeResult)")
  }
}

func gcd(_ xInput: Int, _ yInput: Int) -> Int {
  var largeVal = max(xInput, yInput)
  var smallVal = min(xInput, yInput)
  var remVal = 0

  repeat {
    remVal = largeVal % smallVal
    largeVal = smallVal
    smallVal = remVal
  } while remVal > 0

  return largeVal
}

func getSmallerGcdPair(_ xRatio: Int, _ yRatio: Int, _ largeResult: Int) -> Int {
  let largeRatio = max(xRatio, yRatio)
  let smallRatio = min(xRatio, yRatio)

  return largeResult / largeRatio * smallRatio
}

main()

PHP

<?php
const x = 30;
const y = 100;
const max = 500;

define('gcdResult', gcd(x, y));
define('xRatio', x / gcdResult);
define('yRatio', y / gcdResult);
echo "Maximales Engagement: ".gcdResult." => ".xRatio.":".yRatio.PHP_EOL;

const largeResult = max;
define('smallResult', getSmallerGcdPair(xRatio, yRatio, largeResult));
if(x > y) {
  echo x.":".y." => ".largeResult.":".smallResult.PHP_EOL;
} else {
  echo x.":".y." => ".smallResult.":".largeResult.PHP_EOL;
}

function gcd($xInput, $yInput): int {
  $largeVal = max($xInput, $yInput);
  $smallVal = min($xInput, $yInput);
  $remVal = 0;

  do {
    $remVal = $largeVal % $smallVal;
    $largeVal = $smallVal;
    $smallVal = $remVal;
  } while($remVal > 0);
  
  return $largeVal;
}

function getSmallerGcdPair($xRatio, $yRatio, $largeResult): int {
  define('largeRatio', max($xRatio, $yRatio));
  define('smallRatio', min($xRatio, $yRatio));

  return $largeResult / largeRatio * smallRatio;
}

JavaScript

function main() {
  const x = 30
  const y = 100
  const max = 500

  const gcdResult = gcd(x, y)
  const xRatio = x / gcdResult
  const yRatio = y / gcdResult
  console.log(`Maximales Engagement: ${gcdResult} => ${xRatio} : ${yRatio}`)

  const largeResult = max
  const smallResult = getSmallerGcdPair(xRatio, yRatio, largeResult)
  if(x > y) {
    console.log(`${x}:${y} => ${largeResult}:${smallResult}`)
  } else {
    console.log(`${x}:${y} => ${smallResult}:${largeResult}`)
  }
}

const gcd = (xInput, yInput) => {
  let largeVal = Math.max(xInput, yInput)
  let smallVal = Math.min(xInput, yInput)
  let remVal = 0

  do {
    remVal = largeVal % smallVal
    largeVal = smallVal
    smallVal = remVal
  } while(remVal > 0)

  return largeVal
}

const getSmallerGcdPair = (xRatio, yRatio, largeResult) => {
  const largeRatio = Math.max(xRatio, yRatio)
  const smallRatio = Math.min(xRatio, yRatio)

  return largeResult / largeRatio * smallRatio
}

main()

Java

import java.util.*;

public class Main {
  public static void main(String[] args) throws Exception {
    final int x = 30;
    final int y = 100;
    final int max = 500;

    final int gcdResult = gcd(x, y);
    final int xRatio = x / gcdResult;
    final int yRatio = y / gcdResult;
    System.out.println("Maximales Engagement: " + gcdResult + " => " + xRatio + " : " + yRatio);

    final int largeResult = max;
    final int smallResult = getSmallerGcdPair(x, y, largeResult);
    if(x > y) {
      System.out.println(x + ":" + y + " => " + largeResult + ":" + smallResult);
    } else {
      System.out.println(x + ":" + y + " => " + smallResult + ":" + largeResult);
    }
  }

  private static int gcd(int xInput, int yInput) {
    int largeVal = Math.max(xInput, yInput);
    int smallVal = Math.min(xInput, yInput);
    int remVal = 0;

    do {
      remVal = largeVal % smallVal;
      largeVal = smallVal;
      smallVal = remVal;
    } while(remVal > 0);

    return largeVal;
  }

  private static int getSmallerGcdPair(int xRatio, int yRatio, int largeResult) {
    final int largeRatio = Math.max(xRatio, yRatio);
    final int smallRatio = Math.min(xRatio, yRatio);

    return largeResult / largeRatio * smallRatio;
  }
}

Vergleichen Sie den Code

Da es sich um einen einfachen Code handelt, denke ich, dass Sie ihn lesen können, ohne sich dessen bewusst zu sein, selbst in einer Sprache, mit der Sie normalerweise nicht befasst sind. Es gibt sicherlich Macken beim Schreiben für jede Sprache, aber umgekehrt scheint der Unterschied so groß zu sein.


Zusammenfassung


Bonus

Nur Kotlin, aber ich werde eine rekursive Schreibweise schreiben, die das maximale Engagement bietet.

gcd(Math.max(x, y), Math.min(x, y))
tailrec fun gcd(largeInput: Int, smallInput: Int): Int 
  = if(smallInput == 0) largeInput else gcd(smallInput, largeInput % smallInput)

Recommended Posts

Eine Geschichte über das Schreiben einer Verhältnisberechnung in einer internen Lernsitzung
Eine Geschichte über das Schreiben einer Dichotomiemethode in einer internen Lernsitzung
Eine Geschichte darüber, wie sich das Verhalten junger Menschen bei einer 15-minütigen Lernsitzung jeden Morgen überraschend verbesserte
Eine Geschichte darüber, wie sich das Verhalten junger Menschen bei einer 15-minütigen Lernsitzung jeden Morgen überraschend verbesserte
Eine Geschichte über das Schreiben einer Verhältnisberechnung in einer internen Lernsitzung
Eine Geschichte über das Schreiben einer Dichotomiemethode in einer internen Lernsitzung
Die Geschichte des Besuchs der Docker + k8s-Lernsitzung [JAZUG Women's Club x Java Women's Club]
Die Geschichte des Besuchs der Docker + k8s-Lernsitzung [JAZUG Women's Club x Java Women's Club]
[Inhouse-Studiensitzung] Behandlung von Java-Ausnahmen (26.04.2017)
Studiennotizen für einen Job bei einem IT-Unternehmen von unerfahrenen
Die Geschichte eines arithmetischen Überlaufs, der in Ruby nicht auftreten sollte