2017-09-30 2 views
1

Lorsque l'on regarde un morceau de code récemment, je suis tombé sur une ligne qui me avait penser:Le produit de deux flotteurs positifs peut-il être négatif?

if a*b > 0: 
    # do stuff 

Il faut supposer que a et b sont flotteurs.

Question: Est-il
possible qu'il existe (très faible, positif, et probablement près de ~ eps_mach) les valeurs de a et b de telle sorte que leur produit est négatif? Si non, pourrait-il être que nous avons a*b==0 avec ni a==0 ni b==0.

Pour ne pas être un empoté complet, voici mes pensées:

  1. Non, il est possible puisque dans FP l'arithmétique du produit est probablement défini de telle sorte que les bits de signe de a et b déterminez le bit de signe a*b. Ainsi, à un certain niveau de base, le calcul s'exécute "Bit de signe de note de a est positif." Bit de signe de note de b est positif. J'imagine que cette convention est spécifiée et universellement classée quelque part à condition qu'elle existe.

  2. Le a*b==0 avec a!=0 et b!=0 semble certainement possible.

  3. La réponse dépend de l'ordinateur et de la langue.

Cela me conduit à une sous-question:

Question:
Serait-il plus sûr de mettre en œuvre le code ci-dessous? Si ce n'est pas plus sûr, comment devrait-il être fait?

if (a>0 and b>0) or (a<0 and b<0): 
    # do stuff 
+0

@old_timer Pourquoi voudriez-vous attendre à un NaN plutôt que l'infini positif? –

+0

@old_timer IEEE754 appelle l'infini, tout comme la spécification du langage Java. D'autres langues peuvent faire quelque chose de bizarre, mais je m'attendrais généralement à l'infini. Cela fait une différence parce que NaN> 0, comme toutes les comparaisons de NaN, est faux. –

+0

Ill supprimer mes commentaires. –

Répondre

2

Selon la norme IEEE-754 (avec le mode d'arrondi par défaut), le résultat d'une opération à virgule flottante (bla bla transcendantales) est arrondi au nombre représentable le plus proche. Le produit de deux nombres positifs quelconques est positif, donc dans le pire des cas, le nombre représentable le plus proche est zéro. Il n'y a aucun moyen pour que le nombre représentable le plus proche soit négatif.

Votre code alternatif proposé est correct. Pour les langues avec une fonction sgn/signum, vous pouvez également faire quelque chose comme if sgn(a)*sgn(b) > 0.

+0

Excellent! Merci beaucoup. – floater

3

Les deux morceaux de code ne sont pas équivalents, car le produit de deux nombres positifs mais minuscules peut en effet être nul.

Ce qui est correct dépend de l'objet du test.

Si le code suivant nécessite que le produit soit strictement positif, vous avez besoin du formulaire a*b > 0, et non des tests sur les valeurs individuelles.

Si chaque valeur doit être strictement positive, faites un test pour cela.

Le test que vous proposez est correct si l'exigence est qu'elles sont toutes deux non-nulles et portent le même signe.

Voici un programme Java qui teste certains des cas, y compris les minuscules, mais strictement positif:

public class Test { 
    public static void main(String[] args) { 
    testit(Double.MIN_VALUE, Double.MIN_VALUE); 
    testit(-Double.MIN_VALUE, -Double.MIN_VALUE); 
    testit(1e-320, 1e-320); 
    testit(1e300, 1e300); 
    } 

    public static void testit(double a, double b) { 
    System.out.println("a="+a+" b="+b); 
    System.out.println("a*b > 0 " + (a * b > 0)); 
    System.out.println("(a>0 && b>0) " + (a > 0 && b > 0)); 
    System.out.println("(a<0 && b<0) " + (a < 0 && b < 0)); 
    System.out.println(); 
    } 
} 
+0

Ah, oui. Un hoquet dans ma question. Le test initial que j'ai énuméré était un "raccourci" pour déterminer si exactement un de a ou b est négatif. Cela m'a traversé l'esprit comme étant dangereux, ce qui a été confirmé maintenant. – floater