[Perl] nombre en mots
Dominix
d.minix at gmail.com
Lun 22 Fév 20:43:02 CET 2016
bon, chacun mettra a son goût, j'ai ajusté les vingt _et_ un et les 's'
des cents.
pour passer des paramètres via URL, est ce que le plus simple c'est une
app/dancer ? plack ? mojolicious ?
merci de vos avis (c'est ma question de départ au final) ... bon je vais
voir si hollande arrive, c'est pas souvent qu'il passe dans ma rue.
Le 22/02/2016 01:22, Sébastien Moretti a écrit :
> Ça dépend des suisses (des cantons) mais c'est plutôt huitante par ici.
>
>> A ma connaissance, les Belges utilisent quatre-vingts. Mais je crois que
>> les Québecois utilisent octante (et peut-être les Suisses).
>>
>>
>>
>> Le 22 février 2016 à 10:30, Dominique <d.minix at gmail.com
>> <mailto:d.minix at gmail.com>> a écrit :
>>
>> houla, l'octante c'est faite la malle ;-)
>>
>> Le 21 février 2016 à 20:44, Alain BarBason <alain at barbason.be
>> <mailto:alain at barbason.be>> a écrit :
>>
>> Le 22/02/16 06:55, Dominique a écrit :
>>
>> suite a qq échange, j'ai pondu la version fr de nombre en
>> mots (ci joint)
>>
>> Version belge
>> septante quatre-vingt nonante ) );
>>
>> :-)
>>
>> Abb
>
-------------- section suivante --------------
#!/usr/bin/perl
# This is an 79-character-wide ASCII-encoded Perl-source-code text file.
# =======|=========|=========|=========|=========|=========|=========|=========
###############################################################################
# Writes a number in words. #
# Eg, given "398", outputs "trois cent quatre-vingt dix huit" #
# Input: A single command-line argument consisting of a non-negative integer. #
# Ootput: The number in words. #
# Author: Robbie Hatley for english original, adapté en fraçais par dominix #
# Edit history: #
# Sat Feb 20, 2016 - Wrote it. #
# Sat Feb 21, 2016 - version française (dominix) #
# NB la version belge est activable par le changement du commentaire 80 vs 81 #
###############################################################################
use v5.018;
use strict;
use warnings;
sub nombre_en_mots ($);
# main body of script:
{
if ( 1 != @ARGV )
{
die "Error: This program takes exactly one argument, which must be\n",
"a non-negative integer not exceeding 10^66-1.\n",
"$!\n";
}
my $number = shift;
say nombre_en_mots($number);
exit 0;
}
sub nombre_en_mots ($)
{
return "pas d'entrée input" if @_ < 1;
return 'entrée excessive' if @_ > 1;
my $number = shift; # input string
return 'entrée indéfinie' if not defined $number;
return "n'est pas un entier non negatif" if $number !~ m/^[\d]+$/;
return 'dépassement' if length($number) > 66;
return 'zéro' if 0 == $number;
# Dissect the number into its digits little-endian-wise,
# so that the digit index is equal to log10 of place value.
# While this is backwards from the way people read numbers,
# it makes the programming MUCH easier.
my @digits = ();
unshift @digits, $_ for split //, $number;
# Right-zero-pad @digits as necessary so that it will have
# exactly 66 elements (usually most of them zeros):
my $index = 0;
for ( $index = scalar(@digits) ; $index < 66 ; ++$index )
{
push @digits, 0;
}
my @groups = ( '' , qw( mille
million milliard
billion billiard
trillion trilliard
quadrillion quadrilliard
quintillion quintilliard
sextillion sextilliard
septillion septilliard
octillion octilliard
nonillion nonilliard
decillion decilliard) );
my @ones = ( '', qw( un deux trois
quatre cinq six
sept huit neuf ) );
my @tens = ( '', qw( dix vingt trente
quarante cinquante soixante
soixante-dix quatre-vingt quatre-vingt-dix ) );
# septante octante nonante ) );
my @hundreds = ( '', 'cent', 'deux cent', 'trois cent',
'quatre cent', 'cinq cent', 'six cent',
'sept cent', 'huit cent', 'neuf cent' );
my $string = ''; # output string
# Iterate through digit groups of @digits in reverse order
# (right to left, most-significant to least-significant,
# remembering that we're writing all number BACKWARDS on purpose,
# so that the digits are ordered ones, tens, hundreds, thousands, etc)
# and separate out each group in turn as a slice:
for (reverse 0..21)
{
my @slice = @digits[3*$_+0, 3*$_+1, 3*$_+2];
#If this slice is populated:
if ($slice[2] > 0 || $slice[1] > 0 || $slice[0] > 0 )
{
# if hundreds:
if ($slice[2] > 0)
{
$string .= $hundreds[$slice[2]];
# if we also have tens or ones, append ' ':
if ($slice[1] > 0 || $slice[0] > 0)
{
$string .= ' ';
}
else
{
$string .= 's' if ($slice[2] > 1)
}
}
# if tens:
if ($slice[1] > 0)
{
if ( $tens[$slice[1]] =~ /dix$/ ) {
$string .= ($slice[0] == 1) ? "$tens[$slice[1]-1] onze"
: ($slice[0] == 2) ? "$tens[$slice[1]-1] douze"
: ($slice[0] == 3) ? "$tens[$slice[1]-1] treize"
: ($slice[0] == 4) ? "$tens[$slice[1]-1] quatorze"
: ($slice[0] == 5) ? "$tens[$slice[1]-1] quinze"
: ($slice[0] == 6) ? "$tens[$slice[1]-1] seize"
: ($slice[0] == 7) ? $tens[$slice[1]].'-'.$ones[$slice[0]]
: ($slice[0] == 8) ? $tens[$slice[1]].'-'.$ones[$slice[0]]
: ($slice[0] == 9) ? $tens[$slice[1]].'-'.$ones[$slice[0]]
: $tens[$slice[1]]
} else {
$string .= $tens[$slice[1]];
# if we also have ones, append ' ':
if ($slice[0] > 0)
{
#$string .= ' '.$ones[$slice[0]];
$string .= ($slice[0] == 1) ? ' et un'
: ' '.$ones[$slice[0]]
}
}
}
if ($slice[1] == 0 and $slice[0] > 0) {
# tout ça juste pour ne pas avoir "un mille"
$string .= $ones[$slice[0]] if not (($slice[2]==0)&&($slice[0]==1)&&($_==1))
}
# Finally, if this is not the least-significant group,
# append group name (thousand, million, billion, whatever):
if ($_ > 0)
{
$string .= ' ';
$string .= $groups[$_];
}
} # end if (slice is populated)
# If this is not the least-significant group,
# and if both current and next group are populated,
# then append comma and space:
if ($_ > 0)
{
my @nexts = @digits[3*$_-3, 3*$_-2, 3*$_-1];
if
(
($slice[2] > 0 || $slice[1] > 0 || $slice[0] > 0 )
&&
($nexts[2] > 0 || $nexts[1] > 0 || $nexts[0] > 0 )
)
{
$string .= ', ';
} # end appending ', ' if necessary
} # end if (not least-significant group)
} # end for (each group)
$string =~ s/ / /g;$string =~ s/^ //;
# We're done, so return $string:
return $string;
}
Plus d'informations sur la liste de diffusion Perl