Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Grille de nombres-croises

48 réponses
Avatar
candide
Tous les prétextes sont bons pour faire du C : compléter la grille 4x4
ci-dessous par des chiffres décimaux (deux zéros sont déjà placés) en
sorte que tous les nombres de 4 chiffres (lus de la gauche vers la
droite ou de haut en bas) qui apparaissent soient des multiples de 97 :

0XXX
XX0X
XXXX
XXXX


Il n'y a pas que la solution triviale. Bon amusement.

10 réponses

1 2 3 4 5
Avatar
candide
Jean-Marc Bourguet a écrit :

Dans tous les contextes ou c'est observable,



Parce qu'il y a des contextes où ce n'est pas observable ? Exemple ?

les expressions entieres
constantes doivent se comporter comme si elles etaient evaluees a la
compilation



Qu'est-ce que ça veut dire "se comporter comme si elle étaient évaluées
à la compilation" et sans être évaluées ? Et pourquoi te restreins-tu
aux expressions _entières_ ? Et où la norme dit-elle exactement cela ?



(en particulier, elles peuvent apparaitre comme taille de
tableaux en C90).



Pas compris le lien avec la phrase précédente.

En pratique, la mecanique pour faire ces calculs a la
compilation doivent donc etre la car ne pas les avoir *compliquerait*
l'implementation.



Tu n'es pas catégorique : tu dis "la mécanique pour faire les calculs
doivent donc être là". On dirait le sketch de Pierre Dac "il peut le
faire ? oui, il peut le faire".

Oui mais alors le compilateur ne pourrait-il _documenter_ qu'il evalue
les expressions constantes à la compilation ?



Si tu as un compilateur pour lequel c'est un probleme de performance, le



Comment savoir si les constantes sont évaluées à la compilation ? faut
faire des tests ? Par exemple, que fait gcc ? que fait tigcc
(compilateur pour 68k sur calculatrice TI) ?
Avatar
Marc Boyer
On 2008-11-18, candide wrote:
Marc Boyer a écrit :
Mais la norme ne te garantie pas non plus que le compilo ne fera pas
calculer au processeur les statistiques du dernier tierce entre
chaque intruction, ou qu'il utilisera bien l'instruction de multiplication
du processeur et ne calculera pas les multiplications par sommes successives.



Oui, c'est l'argument qu'a déjà donné Antoine mais qui n'est pas probant
dans la mesure où je n'ai aucun contrôle sur ce type de comportement
fantasque du compilateur. Par contre, en utilisant BORNE dans de
nombreuses boucles imbriquées

#define BORNE (BASE*BASE*BASE*BASE)

je prends le risque de faire faire au processeur de nombreux calculs
inutiles pendant l'exécution.



Je pense que ce risque n'existe pas avec un compilateur
reconnu.

Pourquoi ne le faits-tu pas ? A ton avis, quel est le risque majeur
de l'informatique des années 2000 ? Avoir un code non maintenable ou
avoir un code qui rame ?




Je ne vois pas le rapport avec notre problème. Tu veux dire que sous
prétexte que les processeurs sont rapides aujourd'hui, on peut se
permettre de faire l'impasse sur certaines optimisations basiques ?



Si elles sont au détriment de la maintenabilité, oui.

Je
ne suis pas compétent pour répondre ayant une vue très étroite de
l'informatique des années 2000 mais j qu'on a besoin dans certaines
circonstances de code qui soit bien optimisé. Par ailleurs, je ne vois
pas pourquoi tu opposes rapidité et maintenabilité.



Parce que, dans de nombreux cas, rapidité et maintenabilité s'opposent.
Tu as dit toi même:
Pour une question de lisibilité, tu penses bien que je préfèrerais écrire
#define BASE 10
#define BORNE (BASE*BASE*BASE*BASE)



Sur un autre registre, un stockage de quelques données sera bien
plus facile à écrire et maintenir en utilisant un tableau ou une liste
chainée plutôt qu'un arbre binaire équilibré ou une table de hashage,
mais moins efficace potentiellement.

L'opposition maintenance/performance est un très vieux problème
de l'informatique.

Nous sommes en l'an 2000, et je pense que les utilisateurs sont plus
génés par les bugs que par la vitesse/lenteur (bon, parfois, sur certains
systèmes, il parait qu'ils ont les deux ;-) ).

Je faisais parfois des estimations à la louche pour mes étudiants.
Une heure de programmation coute entre 50 et 500 euros (parce qu'à
chaque heure de prog, il faut rajouter une heure de test, la
recette, la comta, etc).
La différence entre un PC avec un Core Duo à 1Gh et un Core Duo à
3Gh est de 100 euro chez Dell. Un processeur moderne effectue à la louche
10-200 millions d'instructions à la seconde.
Pour qu'une optimisation qui prend 10mn à faire soit rentable, il
faut qu'elle permette d'économiser plusieurs millions d'exécution
d'instructions...

Le compilo pourrait même la calculer 3*(3*n) fois, c'est à dire la
calculer 3 fois chaque fois qu'il en a besoin, et vérifier que
les 3 valeurs sont les mêmes, et sinon, choisir par un vote.



Mais bien sûr. Et tu vas peut-être me dire qu'il est vain de sortir par
temps de pluie avec un parapluie rouge car Eole pourrait décider de
faire subir un effet de lévitation mortelle aux porteurs de tels parapluies.



Non, non, je te parle de stratégie plausible d'un code embarqué
dans un environnement électromagnétique où les taux de bug du processeur
sont non négligables (genre satellite).

Ce que tu racontes là est assez invraisemblable. Par contre, que le
processeur soit amené à calculer n fois le produit et cela de façon
totalement inutile me le paraît moins.



Qu'un compilo reconnu fasse ce genre de chose m'étonnerait fort
(hormis en mode débug).

Marc Boyer
--
En France, un habitant sur 1000 est en prison.
Aux USA, 7 habitants sur 1000 sont en prison.
Est-ce que les USA sont 7 fois plus sûrs ?
Avatar
Marc Boyer
On 2008-11-18, candide wrote:
Si tu as un compilateur pour lequel c'est un probleme de performance, le



Comment savoir si les constantes sont évaluées à la compilation ?



Tu regardes l'assembleur généré.

Marc Boyer
--
En France, un habitant sur 1000 est en prison.
Aux USA, 7 habitants sur 1000 sont en prison.
Est-ce que les USA sont 7 fois plus sûrs ?
Avatar
candide
Marc Boyer a écrit :
On 2008-11-18, candide wrote:
Si tu as un compilateur pour lequel c'est un probleme de performance, le


Comment savoir si les constantes sont évaluées à la compilation ?



Tu regardes l'assembleur généré.




Comme quoi pour faire du C convenable, il faut avoir un background
beaucoup plus large. Je sais pas si tu te rends comptes : pour répondre
à une question aussi naturelle que celle que j'ai posée, il faut
apprendre un assembleur.

En plus, tu le sauras juste sur une cible. Et qu'est-ce qui prouve que
s'il évalue ici, il évaluera encore là ?


Je vais peut-être dire une grosse c****** mais serait-il possible que le
compilateur ne soit pas capable d'effectuer l'évaluation mais que
l'environnement d'exécution lui en soit capable ?

Sinon, tu crois pas que ce serait quand même plus simple si le
compilateur documentait l'évaluation / non évaluation ? La doc, encore
la doc, toujours la doc ...
Avatar
Erwan David
candide écrivait :

Marc Boyer a écrit :
On 2008-11-18, candide wrote:
Si tu as un compilateur pour lequel c'est un probleme de performance, le


Comment savoir si les constantes sont évaluées à la compilation ?



Tu regardes l'assembleur généré.




Comme quoi pour faire du C convenable, il faut avoir un background
beaucoup plus large. Je sais pas si tu te rends comptes : pour répondre
à une question aussi naturelle que celle que j'ai posée, il faut
apprendre un assembleur.



Comme on t'a déjà di : ce genre de considération n'est *pas* couvert par
la norme. Par contre en pratique (lire avec tous les compilateurs
normaux) ça se passe comme il faut.

En plus, tu le sauras juste sur une cible. Et qu'est-ce qui prouve que
s'il évalue ici, il évaluera encore là ?




Quand on parle de compilateur pour ce genre de considération d'ultra-bas
niveau, ça contient aussi le backend, donc de toute façon compiler pour
une autre plateforme signifie qu'on utilise un autre compilateur.

Je vais peut-être dire une grosse c****** mais serait-il possible que le
compilateur ne soit pas capable d'effectuer l'évaluation mais que
l'environnement d'exécution lui en soit capable ?



Si tu veux pinailler, la norme n'impose pas d'avoir une séparation entre
compilateur et environnement d'exécution.

Sinon, tu crois pas que ce serait quand même plus simple si le
compilateur documentait l'évaluation / non évaluation ? La doc, encore
la doc, toujours la doc ...



Personne ne lirait une doc de 5000 pages...

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
Jean-Marc Bourguet
candide writes:

Comment savoir si les constantes sont évaluées à la compilation ?



On va reprendre d'une autre maniere.

Toute la definition du C90 est concue pour que certaines expressions
entieres soient evaluees a la compilation (les deux exemples qui me
viennent a l'esprit sont: les expressions controlant le preprocesseur et la
taille des tableaux) parce qu'elles ne peuvent utiliser que des valeurs
connues a la compilation. Je doute fort qu'il y ait jamais eu un
compilateur qui ne le faisait pas (un compilateur qui refuserait de
compiler avec autre chose qu'une constante dans ces contextes est beaucoup
plus vraisemblable).

A partir du moment ou tu as toute la machinerie necessaire pour evaluer ces
expressions (et tu l'as peut-etre deux fois, parce que partager cette
machinerie entre le preprocesseur et le reste du compilateur n'est pas
necessairement la meilleure architecture du code), ne pas l'utiliser pour
toutes les expressions entieres pouvant etre evaluees a la compilation
semble etrange.

Et pourquoi te restreins-tu aux expressions _entières_ ?



Le probleme est plus complexe pour les expressions flottantes. Au minimum:

1/ je ne connais pas de contextes ou les expressions flottantes sont
contraintes a n'utiliser que des valeurs connues a la compilation.

2/ on peut jouer sur les modes d'arrondi pour avoir un resultat different
suivant le mode d'arrondi

3/ que doit faire un compilateur generant du code devant etre executer sur
une cible differente de la machine executant le compilateur?

Par exemple, que fait gcc ?



gcc fait des optimisations autrement poussees (pour commencer l'evaluation
des expressions flottantes -- gcc passe par de l'arithmetique a precision
non bornee pour cela).

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Marc Boyer
On 2008-11-18, candide wrote:
Marc Boyer a écrit :
On 2008-11-18, candide wrote:
Si tu as un compilateur pour lequel c'est un probleme de performance, le


Comment savoir si les constantes sont évaluées à la compilation ?



Tu regardes l'assembleur généré.




Comme quoi pour faire du C convenable, il faut avoir un background
beaucoup plus large.



Ça dépend de la définition de "convenable". Si tu cherches en effet
à controler le "nombre d'évaluation", il faut savoir ce qu'est une
"évaluation", comment elle est générée, etc.

Et puis personne ne t'a parlé de déroulement de boucles en plus.

Je sais pas si tu te rends comptes : pour répondre
à une question aussi naturelle que celle que j'ai posée, il faut
apprendre un assembleur.



Et oui. Et pour faire un code pas trop pourri en terme d'E/S, il
faut avoir des notions en système d'exploitation.

En plus, tu le sauras juste sur une cible. Et qu'est-ce qui prouve que
s'il évalue ici, il évaluera encore là ?



En théorie rien. En pratique, le fonctionnement des compilos
multi-plateforme, c'est de faire d'abord un "pseudo-code", de
l'optimiser, puis de faire l'ASM cible, éventuellement optimisé
encore. Le coup de l'évaluation, je pense que c'est fait dans
le pseudo-code. Mais bon...

Je vais peut-être dire une grosse c****** mais serait-il possible que le
compilateur ne soit pas capable d'effectuer l'évaluation mais que
l'environnement d'exécution lui en soit capable ?



Oui et non.
Dans le cas où n provient d'une entrée utilisateur, le compilo ne
peut pas l'évaluer, car il ne connait pas la valeur. Mais il sait
transformer ton code
for(int i=0 ; i < 3*n ; i+= 3){
...
}
en
const int n3 = 3*n;
for(int i=0 ; i < n3 ; i+= 3){
....
}

Dans le cas où n est connu à la compilation, comme l'a expliqué
Antoine, comme l'expression 3*n pourrait servir de dimension à
un tableau, le compilo *doit* etre capable d'en évaluer le signe.
Le plus simple pour se faire, c'est d'évaluer la valeur.

Sinon, tu crois pas que ce serait quand même plus simple si le
compilateur documentait l'évaluation / non évaluation ? La doc, encore
la doc, toujours la doc ...



Qui est prêt à payer pour cela ? Les compilateurs ne tombent pas
du ciel. Il y a des gens qui les écrivent, et qui écrivent les docs.
Et écrire une doc est un exercice pas facile: il faut satisfaire le
débutant comme l'expert, ne pas noyer le débutant sous des infos
inutiles, etc...

La question de savoir si on peut raler sur la qualité d'un produit
dépend des relations que l'on a avec le fournisseur.

Marc Boyer
--
En France, un habitant sur 1000 est en prison.
Aux USA, 7 habitants sur 1000 sont en prison.
Est-ce que les USA sont 7 fois plus sûrs ?
Avatar
Erwan David
Marc Boyer écrivait :


Oui et non.
Dans le cas où n provient d'une entrée utilisateur, le compilo ne
peut pas l'évaluer, car il ne connait pas la valeur. Mais il sait
transformer ton code
for(int i=0 ; i < 3*n ; i+= 3){
...
}
en
const int n3 = 3*n;
for(int i=0 ; i < n3 ; i+= 3){
....
}



Attention cette optimisation n'est pas valide si on change la valeur de
n dans le corps de la boucle. (Ou alors je me trompe et c'est cette
modification qui provoque un UB ?)

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
Jean-Marc Bourguet
candide writes:

Marc Boyer a écrit :
> On 2008-11-18, candide wrote:
>>> Si tu as un compilateur pour lequel c'est un probleme de performance, le
>> Comment savoir si les constantes sont évaluées à la compilation ?
>
> Tu regardes l'assembleur généré.


Comme quoi pour faire du C convenable, il faut avoir un background
beaucoup plus large.



Pour programmer convenablement, il faut un background un peu plus large que
la connaissance du langage.

Je sais pas si tu te rends comptes : pour répondre à une question aussi
naturelle que celle que j'ai posée, il faut apprendre un assembleur.



Non. Tu veux extraire une garantie formelle d'une description qui ne
decrit volontairement rien a ce niveau et tu n'acceptes pas la version
pragmatique que je repete encore: les autres contraintes font
qu'implementer un compilateur qui ne le ferait pas serait fortement
bizarre.

Je vais peut-être dire une grosse c****** mais serait-il possible que le
compilateur ne soit pas capable d'effectuer l'évaluation mais que
l'environnement d'exécution lui en soit capable ?



C'est pourquoi on restreint sur les exressions entieres, car les flottants
sont plus bizarre.

Sinon, tu crois pas que ce serait quand même plus simple si le
compilateur documentait l'évaluation / non évaluation ?



Il peut aussi documenter qu'il n'insere pas une boucle d'attente entre deux
instructions. Les contraintes dont je parlais plus haut font bien qu'on
est (presque) a ce niveau de bizarrerie.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Marc Boyer
On 2008-11-18, Erwan David wrote:
Marc Boyer écrivait :


Oui et non.
Dans le cas où n provient d'une entrée utilisateur, le compilo ne
peut pas l'évaluer, car il ne connait pas la valeur. Mais il sait
transformer ton code
for(int i=0 ; i < 3*n ; i+= 3){
...
}
en
const int n3 = 3*n;
for(int i=0 ; i < n3 ; i+= 3){
....
}



Attention cette optimisation n'est pas valide si on change la valeur de
n dans le corps de la boucle. (Ou alors je me trompe et c'est cette
modification qui provoque un UB ?)



Non, j'ai implicitement supposé que le corps de la boucle ne modifiait
pas n. Sans quoi, il est impossible de ne faire qu'une seule évaluation
de tout façon.

Marc Boyer
--
En France, un habitant sur 1000 est en prison.
Aux USA, 7 habitants sur 1000 sont en prison.
Est-ce que les USA sont 7 fois plus sûrs ?
1 2 3 4 5