Heim > Java > javaLernprogramm > Hauptteil

Entmystifizierung der CPF- und CNPJ-Prüfzifferalgorithmen: Ein klarer und prägnanter Ansatz

PHPz
Freigeben: 2024-09-03 12:32:03
Original
610 Leute haben es durchsucht

Demystifying CPF and CNPJ Check Digit Algorithms: A Clear and Concise Approach

Ich erinnere mich noch lebhaft an meine erste Begegnung mit dem CPF-Validierungsalgorithmus (Brazillian ID) während meines Grundstudiums. Als wir uns für ein Praktikum am Institut für Exakte Wissenschaften der UFMG, der Bundesuniversität von Minas Gerais, bewarben, wurden wir gebeten, nach einer kurzen Erläuterung des Algorithmus manuell einen Java-Code zu schreiben, um CPF-Prüfziffern zu validieren.

Seitdem bin ich in verschiedenen beruflichen Kontexten mehrmals auf dieses Problem gestoßen, wobei ich oft darauf zurückgegriffen habe, Lösungen aus dem Internet zu kopieren und einige Unit-Tests hinzuzufügen. Allerdings fallen mir jedes Mal die wiederkehrenden Probleme bei diesen Lösungen auf. Sie basieren tendenziell eher auf einem imperativen Paradigma als auf dem erwarteten objektorientierten Ansatz für Java-Codes. Aber was mich noch mehr stört, ist die hohe kognitive Belastung, die diese Implementierungen mit sich bringen und die es unmöglich macht, den Code zu lesen und die Absicht zu verstehen.

Ein interessierter Entwickler, der diesen Code noch nicht implementieren musste, kann problemlos Lösungen in jeder Programmiersprache finden. Sie werden jedoch tendenziell alle auf die gleiche Weise dargestellt: eine naive Nachbildung der Erklärung, wie die CPF-Prüfziffern implementiert werden. Es scheint, dass sich nur wenige Menschen die Zeit nehmen, die Gründe für diesen Ansatz zu verstehen.

Das Kollisionsproblem

In der Softwareentwicklung findet man das Konzept der Kollisionsvermeidung häufig in Hash-Code-Algorithmen, insbesondere bei der Verwendung des Primzahlmoduls. Die Prüfziffern in CPF (brasilianische ID) und CNPJ (brasilianische Firmen-ID) funktionieren ähnlich und konzentrieren sich auf die Vermeidung von Kollisionen. Dadurch wird sichergestellt, dass eine einfache Ziffernsummierung nicht fälschlicherweise falsche Eingaben validiert, da mehrere Kombinationen dieselbe Summe ergeben können.

Um dies zu mildern, ist es üblich, gewichtete Summen anzuwenden und jede Ziffer mit einem bestimmten Faktor zu multiplizieren. Sie können sich das so vorstellen, als würden Sie die Ziffern entlang einer Linie verteilen. Durch die Multiplikation ist es weniger wahrscheinlich, dass mehrere Ziffern an derselben Position landen. Es macht also Sinn, dass die Position der Ziffer in der Zahl deren Gewicht bestimmt.

Um die Zuverlässigkeit weiter zu erhöhen und das Kollisionsrisiko zu minimieren, wird die Summe modulo 11 gebildet und dieses Ergebnis von derselben Primzahl subtrahiert. Um sicherzustellen, dass die Prüfziffer eine einzelne Ziffer bleibt, werden die Ergebnisse von 10 und 11 in 0 umgewandelt.

Die kognitive Belastung

Der Algorithmus zur Berechnung der Prüfziffern für CPF und CNPJ kann schwer zu verstehen sein. Während die Gesamtmotivation hinter dem Algorithmus klar sein mag, ist es oft schwierig, die spezifische Rolle jedes Teils zu erfassen. Diese Komplexität entsteht teilweise dadurch, dass die Berechnung eine Reihe mathematischer Berechnungen umfasst, die oft in einer einzigen, großen Methode zusammengefasst werden. Darüber hinaus können die Gewichtungen, die normalerweise als unerklärliche Anordnung dargestellt werden, unlogisch erscheinen.

Um dem entgegenzuwirken, konzentriere ich mich darauf, die Menge an Code zu reduzieren, der keine Selbsterklärung enthält. Durch die Einhaltung des Single-Responsability-Prinzips (das „S“ in SOLID) bemühe ich mich, einfachere, verständlichere Methoden zu entwickeln. Ich bemühe mich auch, Schlüsselkonzepte durch aussagekräftige Variablennamen zu definieren, mit dem Ziel, eine allgegenwärtige Sprache innerhalb der Codebasis zu etablieren. Mit diesem Ansatz wollte ich herausfinden, was die für CPF-Prüfziffern verwendete Methode von der für CNPJ verwendeten unterscheidet, da Software, die das eine erfordert, oft das andere benötigt. Die Kernfunktionalität des Codes wird unten gezeigt. Für eine weitere Ansicht, einschließlich des vollständigen Codes und der zugehörigen Komponententests, besuchen Sie bitte mein GitHub-Repository.

  private String getCheckDigits(String document, int maxWeight) {
    final int lengthWithoutCheckDigits = getBaseDigitsLength(document);

    int firstWeightedSum = 0;
    int secondWeightedSum = 0;
    for (int i = 0; i < lengthWithoutCheckDigits; i++) {
      final int digit = Character.getNumericValue(document.charAt(i));
      final int maxIndex = lengthWithoutCheckDigits - 1;
      final int reverseIndex = maxIndex - i;
      firstWeightedSum += digit * calculateWeight(reverseIndex, maxWeight);
      // Index is incremented, starting from 3, skipping first check digit.
      // The first part will be added later as the calculated first check digit times its corresponding weight.
      secondWeightedSum += digit * calculateWeight(reverseIndex + 1, maxWeight);
    }

    final int firstDigit = getCheckDigit(firstWeightedSum);
    // Add the first part as the first check digit times the first weight.
    secondWeightedSum += MIN_WEIGHT * firstDigit;
    final int secondDigit = getCheckDigit(secondWeightedSum);

    return String.valueOf(firstDigit) + secondDigit;
  }

  private int calculateWeight(int complementaryIndex, int maxWeight) {
    return complementaryIndex % (maxWeight - 1) + MIN_WEIGHT;
  }

  private int getCheckDigit(int weightedSum) {
    final var checkDigit = enhanceCollisionAvoidance(weightedSum);
    return checkDigit > 9 ? 0 : checkDigit;
  }

  private int enhanceCollisionAvoidance(int weightedSum) {
    final var weightSumLimit = 11;
    return weightSumLimit - weightedSum % weightSumLimit;
  }
Nach dem Login kopieren

Vergleichen Sie das Ergebnis, das Prüfziffern für CNPJ und CPF berechnet, mit der typischen Lösung im Internet:

public class ValidaCNPJ {

  public static boolean isCNPJ(String CNPJ) {
// considera-se erro CNPJ's formados por uma sequencia de numeros iguais
    if (CNPJ.equals("00000000000000") || CNPJ.equals("11111111111111") ||
        CNPJ.equals("22222222222222") || CNPJ.equals("33333333333333") ||
        CNPJ.equals("44444444444444") || CNPJ.equals("55555555555555") ||
        CNPJ.equals("66666666666666") || CNPJ.equals("77777777777777") ||
        CNPJ.equals("88888888888888") || CNPJ.equals("99999999999999") ||
       (CNPJ.length() != 14))
       return(false);

    char dig13, dig14;
    int sm, i, r, num, peso;

// "try" - protege o código para eventuais erros de conversao de tipo (int)
    try {
// Calculo do 1o. Digito Verificador
      sm = 0;
      peso = 2;
      for (i=11; i>=0; i--) {
// converte o i-ésimo caractere do CNPJ em um número:
// por exemplo, transforma o caractere '0' no inteiro 0
// (48 eh a posição de '0' na tabela ASCII)
        num = (int)(CNPJ.charAt(i) - 48);
        sm = sm + (num * peso);
        peso = peso + 1;
        if (peso == 10)
           peso = 2;
      }

      r = sm % 11;
      if ((r == 0) || (r == 1))
         dig13 = '0';
      else dig13 = (char)((11-r) + 48);

// Calculo do 2o. Digito Verificador
      sm = 0;
      peso = 2;
      for (i=12; i>=0; i--) {
        num = (int)(CNPJ.charAt(i)- 48);
        sm = sm + (num * peso);
        peso = peso + 1;
        if (peso == 10)
           peso = 2;
      }

      r = sm % 11;
      if ((r == 0) || (r == 1))
         dig14 = '0';
      else dig14 = (char)((11-r) + 48);

// Verifica se os dígitos calculados conferem com os dígitos informados.
      if ((dig13 == CNPJ.charAt(12)) && (dig14 == CNPJ.charAt(13)))
         return(true);
      else return(false);
    } catch (InputMismatchException erro) {
        return(false);
    }
  }
}
Nach dem Login kopieren

Dieser Code ist nur für CNPJ!

Abschluss

Auch wenn der Ergebniscode etwas ausführlich erscheint, hat mein Schwerpunkt auf Klarheit und Selbsterklärung zu einem Ergebnis geführt, mit dem ich zufrieden bin. Der Code ist intuitiver gestaltet und bietet ein größeres Vertrauen in seine Richtigkeit. Außerdem sind die meisten Kernfunktionen sichtbar, ohne dass auf der Seite nach unten gescrollt werden muss.

Ich freue mich über alle Vorschläge zur weiteren Verbesserung, also zögern Sie nicht, uns Ihr Feedback mitzuteilen.

Das obige ist der detaillierte Inhalt vonEntmystifizierung der CPF- und CNPJ-Prüfzifferalgorithmen: Ein klarer und prägnanter Ansatz. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!