2009-01-30 10 views
11

En Perl, l'opérateur % semble supposer des entiers. Par exemple:Comment calculez-vous div et mod de nombres à virgule flottante?

sub foo { 
    my $n1 = shift; 
    my $n2 = shift; 
    print "perl's mod=" . $n1 % $n2, "\n"; 
    my $res = $n1/$n2; 
    my $t = int($res); 
    print "my div=$t", "\n"; 
    $res = $res - $t; 
    $res = $res * $n2; 
    print "my mod=" . $res . "\n\n"; 
} 

foo(3044.952963, 7.1); 
foo(3044.952963, -7.1); 
foo(-3044.952963, 7.1); 
foo(-3044.952963, -7.1); 

donne

perl's mod=6 
my div=428 
my mod=6.15296300000033 

perl's mod=-1 
my div=-428 
my mod=6.15296300000033 

perl's mod=1 
my div=-428 
my mod=-6.15296300000033 

perl's mod=-6 
my div=428 
my mod=-6.15296300000033 

Maintenant, comme vous pouvez le voir, je suis venu avec une "solution" déjà pour le calcul div et mod. Cependant, ce que je ne comprends pas, c'est l'effet que le signe de chaque argument devrait avoir sur le résultat. Le div ne serait-il pas toujours positif, étant le nombre de fois que n2 correspond à n1? Comment l'arithmétique est-elle censée fonctionner dans cette situation?

Répondre

8

Étant donné a = qd + r, il existe une ambiguïté lors du calcul du reste pour les valeurs négatives de d.

.: par exemple

L'expression −42 ÷ −5, peut être exprimée soit comme: −42 = 9×(−5) + 3 ou −42 = 8×(−5) + (−2).

Donc le reste est alors soit 3 soit -2.

Pour plus d'informations: Wikipedia:Remainder "Inequality satisfied by the remainder"

En outre, la sortie en cas de nombres négatifs dans mod/div est mise en œuvre dépend dans les langues du logiciel. Voir Wikipedia: Modulo operation (regardez le tableau de droite)

+0

Pour l'arrière-plan mathématique, voir [arithmétique modulaire] (http://www.math.rutgers.edu/~erowland/modulararithmetic.html) et/ou [résumé (ou algèbre élémentaire] (http://www.millersville.edu/~bikenaga/abstract-algebra-1/modular-arithmetic/modular-arithmetic.html). – mctylr

15

Le titre pose une question, le corps un autre. Pour répondre à la question du titre, tout comme dans C, l'opérateur% est un module entier, mais il existe une routine de bibliothèque "fmod" qui est un module à virgule flottante.

use POSIX "fmod"; 

sub foo { 
    my $n1 = shift; 
    my $n2 = shift; 
    print "perl's fmod=" . fmod($n1,$n2), "\n"; 
    my $res = $n1/$n2; 
    my $t = int($res); 
    print "my div=$t", "\n"; 
    $res = $res - $t; 
    $res = $res * $n2; 
    print "my mod=" . $res . "\n\n"; 
} 

foo(3044.952963, 7.1); 
foo(3044.952963, -7.1); 
foo(-3044.952963, 7.1); 
foo(-3044.952963, -7.1); 

donne

perl's fmod=6.15296300000033 
my div=428 
my mod=6.15296300000033 

perl's fmod=6.15296300000033 
my div=-428 
my mod=6.15296300000033 

perl's fmod=-6.15296300000033 
my div=-428 
my mod=-6.15296300000033 

perl's fmod=-6.15296300000033 
my div=428 
my mod=-6.15296300000033 
+0

fmod, hein? Je me suis trompé. Merci beaucoup de l'avoir signalé. – bugmagnet

+0

Quelqu'un connaît-il une alternative telle que 'fmod (-23, 10)' renvoie '7' au lieu de' -3'? – Flimm

+0

suffit d'ajouter 10 si c'est moins de 0? – ysth

Questions connexes