Problème de test logique

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
tonton
Messages : 315
Inscription : mar. 26/avr./2005 15:19

Re: Problème de test logique

Message par tonton »

PAPIPP a écrit :Bonjour à tous

Voici ma petite contribution à ce débat.

Opérateur "=" est à la fois un opérateur d’affectation et un opérateur logique de TEST d’égalité
Comment le compilateur PB se tire de ce pb ?
Pas très bien à mon avis mais cela n’est pas très grave puisque nous pouvons trouver un mode de contournement
Dans l’expression A0=1 c’est l’opérateur d’affectation qui est sollicité.
Dans l’ expression If A0=1 c’est l’opérateur logique.
Mais dans l’expression A0=(Not X=0) quel est l’opérateur sollicité ?
Voyons cela de plus près et regardons les résultats ainsi que les générés ASM DE PB 4,51
remplaçons dans x les 0 par 2 et les 1 par 4 afin d'éviter les valeurs logiques 0 et 1 qui peuvent poser pb à l'interprétation
; *********************************************************************************************
; Niveau de priorité | Opérateurs
; --------------------+---------------------
; 8(haute) | ~,-
; 7 | <<,>>,%, !
; 6 | | , &
; 5 | *,/
; 4 | +,-
; 3 | >,>=,<,<=,=,<>
; 2 | Not
; 1(basse) | And, Or, XOr
******** Dans cette hiérarchie les parenthèses ont été oubliées ont peut les placer au plus haut de cette priorité
;******** l'opérateur d'affectation "=" a lui aussi été oublié il doit être au moins au niveau des parenthèses sinon plus haut

Code : Tout sélectionner

x=4
A_0=(Not x=4)=0
Debug A_0
;**************  généré ASM de A_0=(Not x=4)=0
;  x=4
; 	MOV	 dword [v_x],4
; ; A_0=(Not x=4)=0
; 	MOV	 ebx,dword [v_x]
; 	CMP	 ebx,4
; 	JNE	 No0
; 	XOR	 eax,eax
; 	JMP	 Ok0
; No0:
; 	MOV	 eax,1
; Ok0:
; 	MOV	 ebx,eax
; 	AND	 ebx,ebx
; 	MOV	 dword [v_A_0],0 ====> simple affectation de la valeur 0 a v_A_0 donc à A_0 et non résultat d'une relation logique  
; ; Debug A_0
x=4
A_1=(Not x=4)=1
Debug A_1
;**************  généré ASM de A_1=(Not x=4)=1

; ; x=4
; 	MOV	 dword [v_x],4
; ; A_1=(Not x=4)=1
; 	MOV	 ebx,dword [v_x]
; 	CMP	 ebx,4
; 	JNE	 No1
; 	XOR	 eax,eax
; 	JMP	 Ok1
; No1:
; 	MOV	 eax,1
; Ok1:
; 	MOV	 ebx,eax
; 	CMP	 ebx,1
; 	MOV	 dword [v_A_1],1   ====> simple affectation de la valeur 1 a v_A_1 donc à A_1 et non résultat d'une relation logique 
; ; Debug A_1
;**************** maintenant avec double parenthèses pour essayer que l'opérateur "=" soit un opérateur logique  
x=4
A_0=((Not x=4)=0)
Debug A_0
;**************  généré ASM de A_0=((Not x=4)=0)

; ; x=4
; 	MOV	 dword [v_x],4
; ; A_0=((Not x=4)=0)
; 	MOV	 ebx,dword [v_x]
; 	CMP	 ebx,4
; 	JNE	 No2
; 	XOR	 eax,eax
; 	JMP	 Ok2
; No2:
; 	MOV	 eax,1
; Ok2:
; 	MOV	 ebx,eax
; 	AND	 ebx,ebx
; 	MOV	 dword [v_A_0],0====> simple affectation de la valeur 0 a v_A_0 donc à A_0 et non résultat d'une relation logique 
; ; Debug A_0
; ************  Les doubles parenthèses ne suffisent pas a changer l'opérateur "=" d'affectation en opérarteur logique 


;**************** il existe des opérateurs qui ne nécessitent qu'une opérande. Il sont appelés opérateurs Monadiques.
;**************** Comme Not et un opérateur monadique de priorité  2 nous allons utiliser deux not => qui correspondent à ne rien faire
;**************** Comme "=" Opérateur logique a un niveau de priorité de 3 il faut placer deux NOT de priorité 2 qui ne font rien d'autre que
;**************** d'obtenir que "=" soit une opérateur logique 
x=4
A_0=(Not(Not(Not (x=4))=0))
Debug A_0
;**************  généré de A_0=(Not(Not(Not (x=4))=0))

; ; x=4
; 	MOV	 dword [v_x],4
; ; A_0=(Not(Not(Not (x=4))=0))
; 	MOV	 ebx,dword [v_x]
; 	CMP	 ebx,4
; 	JNE	 No2
; 	XOR	 eax,eax
; 	JMP	 Ok2
; No2:
; 	MOV	 eax,1
; Ok2:
; 	MOV	 ebx,eax
; 	AND	 ebx,ebx
; 	JNE	 No3
; 	XOR	 eax,eax
; 	JMP	 Ok3
; No3:
; 	MOV	 eax,1
; Ok3:
; 	AND	 eax,eax
; 	JE	 No4
; 	XOR	 eax,eax
; 	JMP	 Ok4
; No4:
; 	MOV	 eax,1
; Ok4:
; 	MOV	 dword [v_A_0],eax
; ; Debug A_0

;************************ POUR VERIFICATION INVERSONS LE TEST AVEC 1
x=4
A_1=(Not(Not(Not (x=4))=1))
Debug A_1
; ; x=4
; 	MOV	 dword [v_x],4
; ; A_1=(Not(Not(Not (x=4))=1))
; 	MOV	 ebx,dword [v_x]
; 	CMP	 ebx,4
; 	JNE	 No5
; 	XOR	 eax,eax
; 	JMP	 Ok5
; No5:
; 	MOV	 eax,1
; Ok5:
; 	MOV	 ebx,eax
; 	CMP	 ebx,1
; 	JNE	 No6
; 	XOR	 eax,eax
; 	JMP	 Ok6
; No6:
; 	MOV	 eax,1
; Ok6:
; 	AND	 eax,eax
; 	JE	 No7
; 	XOR	 eax,eax
; 	JMP	 Ok7
; No7:
; 	MOV	 eax,1
; Ok7:
; 	MOV	 dword [v_A_1],eax
; ; Debug A_1
; ********************** Les Résulats sont conforment à la logique CQFD  ****************************
En résumé pour que l'opérateur "=" soit un opérateur logique il faut baisser son niveau de priorité comme dans l'exemple suivant.
A_1=(Not(Not(Not (x=4))=1))

A+
Ce n' est pas parce qu' je ne comprends rien a ce que tu baragouines que je te donne raison..
Peso, je m' en tape de ce genre de 'bug' je me démerde pour que ca marche avec les outils dispo...
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Problème de test logique

Message par PAPIPP »

@ tonton
C’est une remarque très pertinente car j’ai lu sous ta plume que tu te perds dans le basic et que tu ne programmes qu’en ASM

http://www.purebasic.fr/french/viewtopi ... 70#p102470
tonton
oups!! je vois mieux ce que tu veux faire
suffis d un peu de basic pour que je me perde
bref ! ca m a l' air correct .
moi! je ne met pas une ligne basic :lol:

Quelle formule tu veux convertir que j assaye a ma façon?
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Problème de test logique

Message par Ollivier »

@PAPIPP

A te lire, on a l'impression que PureBASIC est une daube mal documentée avec laquelle il faut s'adapter exagérément. Je ne suis pas d'accord... C'est bel et bien le compilateur qui s'adapte de manière quasi-impeccable à l'utilisateur.

Voici un code pour bien comprendre les équivalences et surtout pensez aux parenthèses.

Code : Tout sélectionner

;-------------
; 3 modes de calculs différents traités ensemble pèle-mêle et des résultats stables
;-------------
For A = 0 To 1
      For B = 0 To 1
            Debug "Entrées A B : " + Str(A) + "  " + Str(B)
            
            C = (A = B Or 0)   << 3   |   (A Or B)      << 2   |   (A And B)  << 1     |   (A XOr B) 
            D = (A <> B XOr 1) << 3   |   (A | B)       << 2   |   (A & B) + (A & B)   |   (A ! B)
            E = (Not(A - B) )   * 8   +   ((A + B) Or 0) * 4   +   (A * B)     * 2     +   (A & ~B)|(~A & B)
            
            Debug " "
            Debug "Sortie C = " + Str(C)
            Debug "Sortie D = " + Str(D)
            Debug "Sortie E = " + Str(E)
            Debug "-------------------"
            Debug " " 
      Next
Next
Avatar de l’utilisateur
MLD
Messages : 1124
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

Re: Problème de test logique

Message par MLD »

Ollivier +1
Sans parenthèse ce genre de calcul ou de comparaison devient (même avec une potion magique a base de Chouchen renforcée de produits du térroir), vite un foutoir. :oops: :D
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: Problème de test logique

Message par kelebrindae »

Quoi qu'il en soit, j'ai posté le sujet dans le forums "Bugs" du forum US; on verra bien ce que la PB team va répondre.

Merci à tous !
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Problème de test logique

Message par PAPIPP »

@Ollivier
Je ne vois pas dans ma démonstration un élément permettant de dire que j’ai dénigré PB c’est donc un procès d’intention.

Le procès d'intention est un sophisme consistant à condamner les actes d'une personne en lui prêtant des intentions inavouables et condamnables.
Le caractère invalide de ce raisonnement vient du fait que les intentions ne sont pas prouvées, voire invérifiables.
Elles constituent donc une prémisse insuffisante.

Ceci dit revenons à ce qui me semble un bug.
J’ai réalise une démonstration plus simple sur l’opérateur logique ‘=’.
Seule l’expression avec sortie d est conforme à l’opérateur ‘=’ logique.
Les expressions avec les sorties a b et c sont réalisées avec l’opérateur ‘=’ d’affectation.
Est-ce un bug ou pas ? A mon avis c’est un bug

Code : Tout sélectionner

For i=-1 To 2
  For y=-1 To 2
    Debug "Entrées i y : "+Str(i)+"  "+Str(y)
    Mi=i:My=y
    A=i=y
    b=(i=y)
    c=((i=y))
    d=(Not(Not(i=y)))
    Debug "a="+Str(a)
    Debug "b="+Str(b)
    Debug "c="+Str(c)
    Debug "d="+Str(d)+" seul ce test est toujours bon"
    If Mi<>i Or My<>Y
      Debug "i et y modifiés après test i y : "+Str(i)+"  "+Str(y)
   EndIf
  Next
Next
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Problème de test logique

Message par Ollivier »

Bonjour PAPIPP,
PAPIPP a écrit :@Ollivier
Je ne vois pas dans ma démonstration un élément permettant de dire que j’ai dénigré PB c’est donc un procès d’intention.

Le procès d'intention est un sophisme [...]
Je vais t'éclairer...
Plus haut, PAPIPP a écrit :Comment le compilateur PB se tire de ce pb ?
Pas très bien à mon avis mais cela n’est pas très grave puisque nous pouvons trouver un mode de contournement
Si le mode de contournement est simple et simplement expliqué, ça passe d'écrire ceci. Mais si le mode de contournement n'est pas vite fait expliqué de manière simple, alors je me répète en te disant que ceci donne l'impression que PureBASIC est une daube qui demande à l'utilisateur de s'adapter rudement, ce qui n'est pas le cas.

La solution la plus simple c'est ceci

Code : Tout sélectionner

ResultLogique = (UneVariable = UneAutreVariable) Or 0
On met l'égalité à vérifier entre parenthèse et on lui rajoute une opération logique caduque pour que le compilateur traite l'égalité comme une opération logique. D'ailleurs, à la limite, s'il manque un détail à ce sujet dans la Doc, c'est ce détail. Et pour ce détail qui manque dans la Doc, je te l'accorde volontiers.

Remarque: Une opération logique caduque c'est une opération logique qui n'affecte pas le résultat. Dans ces 4 exemples, X n'est pas logiquement affecté:

Code : Tout sélectionner

X Or 0
X And 1
X Xor 0
Not(Not(X) )
Ces 4 exemples indiquent à chaque fois au compilateur que le résultat doit être logique (a contrario d'un résultat arithmétique binaire ou d'un résultat algébrique).

Au lieu de traiter les 4 opérations, tu t'es appuyé sur une seule d'entre elle : Not(Not(x) ).
Alors (1) ne pas parler de la totalité des quatre possibilités, (2) ne pas choisir la plus simple et (3) choisir la plus compliquée, c'est trois raisons distinctes que tu offres et qui, mises ensemble impliquent que l'utilisateur doit galérer pour arriver à quelque chose de potable!

Il ne faut pas oublier non plus d'expliquer pourquoi on est obligé de faire comme ça.

La première raison, c'est qu'on est obligé de faire comme ça parce qu'il est usuellement rare d'intégrer une égalité logique dans une opération logique. Personnellement, je l'utilise pour automatiser un calcul algébrique (calcul math classique). Mais c'est très lourd, je trouve: tant sur le plan de la lisibilité du code que sur le plan de la performance (puisque la vérification exécute le calcul automatisé même quand la vérification est fausse!).
Exemple:

Code : Tout sélectionner

Result = (3 * Sin(Angle) ) * ((Limite < 0) Or 0)
Equivalent plus lisible et plus performant:

Code : Tout sélectionner

If Limite < 0 ; Limite négative?
   Result = 3 * Sin(Angle) ; Oui: retourne 3 fois le sinus de l'angle
EndIf
La seconde raison, c'est une qualité du compilateur en la matière, c'est de pouvoir traiter tout ce qu'on veut dans la limite du possible: l'algèbre, l'arithmétique binaire et la logique binaire, le tout en un seul calcul!

Il faut donc bien à un moment donné préciser localement dans le calcul ce que l'on fait! Et rajouter « Or 0 » c'est la seule et simplissime précision à fournir!
PAPIPP a écrit :Voyons cela de plus près [...]
; *********************************************************************************************
; Niveau de priorité | Opérateurs
; --------------------+---------------------
; 8(haute) | ~,-
; 7 | <<,>>,%, !
; 6 | | , &
; 5 | *,/
; 4 | +,-
; 3 | >,>=,<,<=,=,<>
; 2 | Not
; 1(basse) | And, Or, XOr
******** Dans cette hiérarchie les parenthèses ont été oubliées ont peut les placer au plus haut de cette priorité
;******** l'opérateur d'affectation "=" a lui aussi été oublié il doit être au moins au niveau des parenthèses sinon plus haut
Tes commentaires sur la documentation des priorités sont faux! Tu sous-entends en évoquant, je cite « l'oubli » donc que PB est mal documenté à ce sujet. Ce que je trouve aussi faux!

Les parenthèses n'ont pas été oubliées puisque ce tableau traite des calculs quand on souhaite justement éviter au maximum de mettre des parenthèses. Et l'instruction « = » n'a pas à être précisée dans ce tableau puisque cette instruction copie des données d'un point A à un point B dans la mémoire de l'ordinateur. Alors que l'opération logique de comparaison d'égalité elle-aussi écrite avec le signe « = » compare 2 données A et B de même nature dans la mémoire de l'ordinateur. Et cette opération-là n'a pas été oubliée puisque elle se situe en priorité 3 dans le tableau.

En revanche, il y a peut-être une subtilité à corriger dans la documentation, c'est qu'à mon avis, Not, Xor, And et Or sont concrètement "dans le même bateau", c'est-à-dire de la même priorité, Not y compris.
PAPIPP a écrit :En résumé pour que l'opérateur "=" soit un opérateur logique il faut baisser son niveau de priorité comme dans l'exemple suivant.
A_1=(Not(Not(Not (x=4))=1))
ça, ça me semble trop compliqué et faux puisqu'il ne faut pas baisser le niveau de priorité de l'opérateur « = » comme dans l'exemple suivant mais il suffit de baisser le niveau de priorité de l'opérateur « = » comme l'exemple suivant, même si l'exemple suivant en question n'est pas simple du tout et loin des facilités offertes par le compilateur.


Conclusion pour PAPIPP:

L'accord à ton encontre induit avec tonton et MLD n'est pas un enrichissement de ma réputation par ton malheur. Je ne souhaite pas ton malheur, et je ne souhaite pas enrichir ma réputation auprès de tonton et MLD, donc il n'y a aucun procès, sois-en assuré !

Voilà mes arguments qui, à mon avis sont exacts et suffisamment dénués de faciles partialités, pour être considérés comme vrais. C'est donc loin d'être un sophisme. Mais j'apprécie humblement tes qualités en langue française aussi, qui sont un enrichissement au forum si elle sont agréablement usées.

Je me permets de t'en inventer un de sophisme:
« Les sages s'expriment souvent par de jolis mots.
Aussi, les sages ne s'interdisent pas de raconter la bêtise humaine.
Donc, la bêtise humaine s'exprime souvent par de jolis mots. » Ollivier !

++
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Problème de test logique

Message par PAPIPP »

Bonjour Ollivier

Merci de cette réponse intelligente et non polémiste.
Je crois pouvoir dire que nous sommes d’accord à 80% sur le pb de fond

Mise à part tout ce qui est interprétation, jugement de valeur ou procès d’intention que je laisse à ces auteurs.
J’évite de les pratiquer ayant pour devise « Un argument ad hominen est un argument de minus habens ».
Peut-être est-ce là un argument qui se retourne contre son auteur.

Revenons sur les 20 % du fond encore de désaccord.

Purebasic est continuellement en évolution et Fred utilise tous les programmeurs de PB pour affiner les tests.
Il faut reconnaître qu’il serait étrange qu’un langage de si haut niveau puisse être exempt de bug.
Par ailleurs un analyseur lexical et syntaxique à une passe est une gageure et ici encore bravo aux concepteurs.
Si précédemment, je n’ai pas pris cette précaution, c’est que je pensais que tout ce que je viens de dire ici est une évidence.
Il m’était donc superflu de rappeler les avantages de ce langage d’autant que mon intervention portait sur un dysfonctionnement de ce langage.

1) Tout d’abord Mea culap sur le niveau d’affectation.
Suivant le principe que plus un niveau est élevé plus il est prioritaire donc plus vite est réalisé l’opération.
Or l’affection est toujours la dernière opération effectuée elle est donc au plus bas niveau contrairement à ce que j’ai dit.
En ce qui concerne le niveau des parenthèses, les expressions sont évaluées d’abord pour les expressions entre les parenthèses.
Elles sont donc toujours un rehausseur de niveau pour l’expression entre parenthèse.
J’ai considéré quelles étaient toujours de plus haut niveau que le reste de l’expression, donc d’un niveau supérieur aux autres opérateurs.
Mais tout ceci est relatif.

2) Dans quelques langages C, C++, APL etc.. l’opérateur ’=’ d’affectation est différent de l’opérateur ‘=’ de test
Ceci facilite le travail de l’analyseur.
Ce n’est pas le cas en PB où les deux opérateurs sont confondus comme dans beaucoup d’autres langages.
Hormis en APL ou tous les opérateurs ont le même niveau, l’analyse se pratique de la gauche vers la droite
et comme l’opérateur d’affection est différent de l’opérateur logique on peut affecter une valeur en plein milieu d’une expression.
Les autres langages ont un opérateur d’affectation au plus bas niveau.
L'’inférence de ce principe est qu’il est difficile voire impossible d’affecter une valeur au milieu d’une expression si l’opérateur logique et d’affection on le même symbole.

En d’autre terme que signifie en PB a=b=c s’il n’y a pas d’erreur de syntaxe comme c’est le cas dans (a=b)=c
ou dans a=b=c=d où il y a une erreur de syntaxe.

J’ai montré dans mes interventions avec le généré ASM ou avec DEBUG que quelque soit le niveau de parenthèse seul fonctionne l’opérateur d’affectation.
Mais qu’elle est l’affection dans l’expression a=b=c ou dans a=(b=c) ou a=((b=c))
Et bien PB affecte toujours la dernière valeur ici C à A mais B reste inchangé il n’est pas affecté.
Dans PB les expressions suivantes sont autorisées par l’analyseur :
a=b=c : a=(b+c) : a=(b=c)=d : ou a=b=(c=d) etc.. je n’ai pas testé toutes les expressions autorisées possibles.
Toutes ces expression sont équivalentes à a=c pour la première et a=d pour les deux suivantes.
Par contre les instructions suivantes sont interdites pour erreur de syntaxe ce qui me semble normal.
a=b=c=d ou a=(b=c=d)

Mais dans tout ceci n’y a t-il pas un bug ?

3°)
PAPIPP a écrit:
En résumé pour que l'opérateur "=" soit un opérateur logique il faut baisser son niveau de priorité comme dans l'exemple suivant.
A_1=(Not(Not(Not (x=4))=1))
ça me semble trop compliqué et faux puisqu'il ne faut pas baisser le niveau de priorité de l'opérateur « = » comme dans l'exemple suivant mais il suffit de baisser le niveau de priorité de l'opérateur « = » comme l'exemple suivant, même si l'exemple suivant en question n'est pas simple du tout et loin des facilités offertes par le compilateur.
Comme je l’ai noté plus haut dans mon mea culpa les niveaux sont relatifs donc si l’on monte A par rapport à B c’est que l’on baisse B par rapport à A Ces deux notions sont équivalentes dans un monde relatif.
Mais par contre le niveau de l’affectation est le plus bas puisque effectué en dernier.
On devra donc remonter ce niveau pour en faire un opérateur logique.

4) Recherche d’un opérateur ‘=’ logique dans une expression PB.
Il faut monter le niveau de l’opérateur d’affectation ‘=’ pour en faire un opérateur logique.
Je n’ai pas chercher très longtemps j’ai favorisé un opérateur monadique comme NOT plutôt qu’un opérateur dyadique comme OR ou AND.

X=(NOT(NOT(expression))
ou X=(expression) OR 0
ou X=(expression) AND 1
ou X=(NOT(Expression inversée))
Mais il faut reconnaître que l’artifice de contournement est étrange et ceci ressemble aussi à un bug.

Code : Tout sélectionner

For i=-1 To 2
  For y=-1 To 2
    Debug "i y=>"+Str(i)+" "+Str(y)
    a=(i=y) Or 0
    b=(i=y) And 1
    c=(Not(Not(i=y)))
    d.b=  (Not(i<>y))
    Debug "a=(i=y or 0 =>"+Str(a)
    Debug "b=(i=y) And 1 =>"+Str(b)
    Debug "c=(Not(Not(i=y))) =>"+Str(c)
    Debug "d=(not(i<>y) =>"+Str(d)
   
  Next
  Next
En conclusion.
Merci de cette discussion pour avoir mis l’accent sur les priorités et en particulier sur le niveau de l’affectation.. C’est relativement plus précis maintenant.
Mais je maintiens qu'il y a au moins un bug.

@+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Répondre