version 0.0021


The RG number is an identification number of Brazilian citizens emitted by the Department of Public Safety, which is called "Secretaria de Segurança Pública (SSP)".

RG stands for "Registro Geral", and it is valid for all brazil territory. May be use as passport to Argentina, Paraguay, Uruguay and Chile.

The RG is comprised of a base of 8 digits and one check digit.

It is usually written like '12.002.999-0' so as to be more human-readable.

This module provides test_rg for checking that a RG number is correct. Here a correct RG number means

  • it is 9 digits long

  • it satisfies the check equation mentioned below

Before checking, any non-digit letter is stripped, making it easy to test formatted entries like '21.002.999-00' and entries with extra blanks like ' 99.221.222-00 '. Except the letter X, because it's represents the number 10.

        test_rg('39.985.676-X') # incorrect RG, returns 0
        test_rg(' 39.985.676-6 ') # is ok, returns 1
        test_rg('123') # nope, returns undef

Tests whether a RG number is correct. Before testing, any non-digit [except X, no matter its case] character is stripped. Then it is expected to be 9 digits long and to satisfy check equation which validate the check digit. See "THE CHECK EQUATIONS".

The policy to get rid of '.' and '-' is very liberal. It indeeds discards anything that is not a digit (0, 1, ..., 9, or X) or letter. That is handy for discarding spaces as well

        test_rg(' 39.985.676-6 ') # is ok, returns 1

But extraneous inputs like '3.9.9 8w5.6w7h6?6' are also accepted. If you are worried about this kind of input, just check against a regex:

        warn "bad RG: only digits (9) expected"
                unless ($rg =~ /^\d{8}(\d|x)$/i);

        warn "bad RG: does not match mask '__.___.___-_'"
                unless ($rg =~ /^\d{2}\.\d{3}\.\d{3}-(\d|x)$/i);

NOTE. Integer numbers like 1234567 with fewer than 8 digits will be normalized (eg. to "001234567") before testing.

        canon_rg(99); # returns '000000099'
        canon_rg('99.999.999-9'); # returns '999999999'

Brings a candidate for a RG number to a canonical form. In case, the argument is an integer, it is formatted to at least 9 digits. Otherwise, it is stripped of any non-alphanumeric [again, except x] characters and returned as it is.

        format_rg('00000000'); # returns '00.000.000-0'

Formats its input into '00.000.000-0' mask. First, the argument is canon'ed and then dots and hyphen are added to the first 9 digits of the result. So you can call format_rg even when its already formated.

        ($base, $dv) = parse_rg($rg);
        $hashref = parse_rg('99.222.111-0'); # { base => '99222111', dv => '0' }

Splits a candidate for RG number into base and check digits (dv - dígitos de verificação). It canon's the argument before splitting it into 8- and 1-digit parts. In a list context, returns a two-element list with the base and the check digits. In a scalar context, returns a hash ref with keys 'base' and 'dv' and associated values.

        $rand_rg = random_rg($valid);

        $correct_rg = random_rg();
        $rg = random_rg(1); # also a correct RG
        $bad_rg = random_rg(0); # an incorrect RG

Generates a random RG. If $valid is omitted or 1, it is guaranteed to be correct. If $valid is 0, it is guaranteed to be incorrect. This function is intented for mass test. (Use it wisely.)

The implementation is simple: just generate a 8-digits random number, hopefully with a uniform distribution and then compute the check digits. If $valid==0, the check digits are computed not to satisfy the check equations.


test_rg is exported by default. canon_rg, format_rg, parse_rg and random_rg can be exported on demand.


Business::BR::RG - Perl module to test for correct RG numbers


        use Business::BR::RG;

        print "ok " if test_rg('390.533.447-05'); # prints 'ok '
        print "bad " unless test_rg('231.002.999-00'); # prints 'bad '

using all methods

        use Business::BR::RG qw /canon_rg test_rg random_rg format_rg parse_rg/;

        test_rg('48.391.390-x') # 1
        canon_rg('11.456.789-x') # '11456789X'

        test_rg('48.190.390-X') # 0

        test_rg('48.190') # undef

        format_rg('') # '48.190.390-X'

        my ($base, $dv) = parse_rg('');
        print $base # '48190390'
        print $dv   # 'X'

        my $hashref = parse_rg('');
        print $hashref->{base} . '-' . $hashref->{dv}; # 48190390-X


A correct RG number has one check digit which are computed from the base 8 first digits. Consider the RG number written as 9 digits

c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] dv[1]

To check whether a RG is correct or not, it has to satisfy the check equations:

c[1]*2 + c[2]*3 + c[3]*4 + c[4]*5 + c[5]*6 + c[6]*7 + c[7]*8 + c[8]*9 + dv[9] * 100 = 0 (mod 11)


until now I do not found any RG that has less than 8 digits. But, I guess, old people still have it. For now, this is the only way that I found to check RG. If you found any bug, feel free to send e-mail, open an issue on github or open a RT.


Note that this module only tests correctness. It doesn't enter the merit whether the RG number actually exists at the Brazilian government databases.

Please reports bugs via CPAN RT or github.

You may be interested too in validation of CPF/CNPJ. So you can look at:



You should too make a search about the Business::BR namespace.



You can find documentation for this module with the perldoc command (to read this)

        perldoc Business\:\:BR\:\:RG


If you want to contribute with the code, you can fork this module on github:

You can even report a issue.


Renato CRON, <>


Copyright (C) 2011 by Renato CRON

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.1 or, at your option, any later version of Perl 5 you may have available.


Renato CRON <>


This software is copyright (c) 2011 by Renato CRON.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 154:

Non-ASCII character seen before =encoding in 'Segurança'. Assuming UTF-8