#1 Le 08/08/2022, à 23:05
- VroumH
Afficher la valeur la plus proche de la moyenne BASH
Bonjour ! !
J'ai besoin d'aide, j'ai deux listes
fichier1
1 -30.133 Orange
1 -6.576 Banane
1 -6.293 Pomme
1 -12.034 Abricot
1 -7,076 Mûre
2 -4,355 Pomme
2 -6,517 Banane
2 -6,355 Abricot
2 -3,502 Mûre
et j'ai les moyens
fichier2
1 -12.4224
2 -5.18225
Je me suis inspiré de la fonction find min() en python3
# create a list
ls = [3, 6, 7, 2, 1, 5]
# find min value using loop
min_val = ls[0]
for val in ls:
if val < min_val:
min_val = val
# display the min value
print(min_val)
#fichier2
#1 -12.4224
#2 -5.18225
#!/bin/bash
grep '1 ' fichier1 > temp2
awk '{ print $2 } ' temp2 > temp3
#temp3
#1 -30.133 Orange
#1 -6.576 Banane
#1 -6.293 Pomme
#1 -12.034 Abricot
#1 -7,076 Mûre
a=($(cat temp3 ))
b=($(cat fichier2 ))
minim=$(expr ${a[0]} - ${b[1]}) # comparaison de la première différence avec la moyenne
for i in $a; do # pour chaque valeur de la liste
if [ $i - "${b[1]}" <= $minim ]; then # si la différence de i avec la moyenne est inférieur à la première différence alors minim devient le différence testée
$minim=i
fi
echo $i
done
Pour les groupes, je voudrais écrire : Pour le groupe 1, Abricot est le plus proche est le plus proche de la moyenne et pour le groupe 2, Pomme est le plus proche de la moyenne.
Hors ligne
#2 Le 08/08/2022, à 23:16
- Watael
Re : Afficher la valeur la plus proche de la moyenne BASH
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#3 Le 09/08/2022, à 13:15
- MixT
Re : Afficher la valeur la plus proche de la moyenne BASH
Après essayes en Python3 c'est déjà un langage plus "dynamique"
Hors ligne
#4 Le 09/08/2022, à 13:35
- Watael
Re : Afficher la valeur la plus proche de la moyenne BASH
déjà, apprendre à rédiger un algorithme, avant de coder.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#5 Le 09/08/2022, à 14:35
- MicP
Re : Afficher la valeur la plus proche de la moyenne BASH
Bonjour
Ouaih !, mais si on commence par dire qu'il faut faire ça en bash et que plus loin on utilise grep awk cat et autres programmes externes,
est-ce qu'il ne faudrait pas commencer par bien définir les règles du jeu ?
Hors ligne
#6 Le 09/08/2022, à 16:33
- Tawal
Re : Afficher la valeur la plus proche de la moyenne BASH
Hello,
De toute façon, en bash, ça va être difficile.
Car il me semble bien que bash ne manipule que des entiers.
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#7 Le 09/08/2022, à 17:30
- MicP
Re : Afficher la valeur la plus proche de la moyenne BASH
… bash ne manipule que des entiers. …
Oui, mais rien n'empêche d'en faire des entiers en enlevant le point décimal, puis en ajoutant un ou deux zéros à la fin si nécessaire (suivant le nombre de décimales de la référence à comparer)
le but étant de comparer leur différences en fonction d'une référence, tout peut très bien être fait en pur bash sans avoir besoin de lancer une commande externe.
En utilisant les redirections et BASH_REMATCH ou simplement read,
on peut extraire les données contenues dans les fichiers
dont le tableau suivant :
tabl_1_Vals=( -30.133 -6.576 -6.293 -12.034 -7.076 )
Et ensuite :
michel@deb114x1t:~$ tabl_1_Vals=( -30.133 -6.576 -6.293 -12.034 -7.076 )
michel@deb114x1t:~$ tabl_1_Tmp=( ${tabl_1_Vals[*]/%/0} ) # Ajouter 1 zéro à la fin de chacun des éléments du tableau
michel@deb114x1t:~$ tabl_1_Tmp=( ${tabl_1_Tmp[*]//./} ) # Supprimer le point décimal qui est dans chacun des éléments du tableau
michel@deb114x1t:~$ echo ${tabl_1_Tmp[*]}
-301330 -65760 -62930 -120340 -70760
michel@deb114x1t:~$
Et voilà ci-dessus un tableau d'entiers prêt à êtres être soustraits et comparés par bash
à la référence -12.4224 à laquelle on aura enlevé le point décimal.
=======
Mais en fait, histoire d'économiser la RAM au cas où les fichiers de données seraient énormes,
on pourrait même se passer de tableau et lire les données une à une directement dans le fichier.
Dernière modification par MicP (Le 09/08/2022, à 19:50)
Hors ligne
#8 Le 09/08/2022, à 18:14
- Tawal
Re : Afficher la valeur la plus proche de la moyenne BASH
Vas-y pour la lourdeur !
Tiens un tableau de nombre décimaux à traiter pour en faire la moyenne :
notes=( 1.024 3.2 5.6487 65.2 2.23548 10.77694 )
Soit on utilise un autre langage, ou alors on s'autorise des commandes externes (si on tient au script bash).
Au passage, awk serait bien indiqué à cette situation ...
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#9 Le 09/08/2022, à 18:48
- MicP
Re : Afficher la valeur la plus proche de la moyenne BASH
… Tiens un tableau de nombre décimaux à traiter pour en faire la moyenne : …
Les moyennes ne sont pas à calculer …
… J'ai besoin d'aide, j'ai deux listes
fichier1
…
et j'ai les moyens
fichier2
…
…puisqu'elles sont données dans fichier2
Mais si tu veux vraiment un résultat approximatif de la moyenne (ci dessous, je ne t'ai mis que les 64 premières décimales) ,
tu peux toujours utiliser la commande externe bc
michel@deb114x1t:~$ notes=( 1.024 3.2 5.6487 65.2 2.23548 10.77694 )
michel@deb114x1t:~$ notesTmp="${notes[@]/#/ + }"; BC_LINE_LENGTH=0 bc <<< "scale=64; ${notesTmp/+ } / ${#notes[@]}"
79.1043366666666666666666666666666666666666666666666666666666666666
michel@deb114x1t:~$
=======
L'algorithme que je propose (sans tableaux) :
Pour plus de clarté, je vais appeler :
- fichDonnees le fichier nommé fichier1
- fichMoyennes le fichier nommé fichier2
lire fichMoyennes ligne par ligne tant qu'il y aura des lignes à lire
en extrayant un numeroMoyenne et valeurMoyenne associée
initialiser valeurMin à valeur du même nombre de chiffres + 1 chiffre tous à 9 (=> valeur maxi possible en fonction du nombre de chiffres dans la valeur)
initialiser chaineMin à chaîne vide
Lire fichDonnees ligne par ligne tant qu'il y aura des lignes à lire (Dans l'exemple, les numeroDonnee sont rangés consécutivement dans l'ordre, mais autant tout lire au cas où)
en extrayant le numeroDonnee, la valeurDonnee, et la chaineDonnee associée
si numeroDonnee est égal à numeroMoyenne, alors
difference = ( valeurDonnee - valeurMoyenne )
si difference est inférieur à valeurMin alors valeurMin = difference et chaineMin = chaineDonnee
fin de lecture de fichDonnees => sortie de la chaineMin et du numeroMoyenne associé
fin de lecture de fichMoyennes
Comme tout ça va se passer dans bash sans avoir à lancer de commande(s) externe(s), ça devrait être assez rapide.
=======
NOTE : Ce n'est pas le cas dans le sujet donné, mais si les valeurs numériques étaient trop grandes (dépassement de capacité de valeur numérique pour bash),
alors il faudrait prévoir de faire des calculs de différence et comparaison
chiffre par chiffre <=> caractère par caractère <=> travailler sur les chaînes de caractères représentant les nombres.
Dernière modification par MicP (Le 09/08/2022, à 23:01)
Hors ligne
#10 Le 09/08/2022, à 19:24
- Tawal
Re : Afficher la valeur la plus proche de la moyenne BASH
Ah oui, j'étais parti sur le calcul des moyennes.
Mais quand même, je pense qu'avec awk, ce serait plus facile.
Lecture des données, tri, comparaison et affichage, c'est un peu son rôle non ?
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#11 Le 09/08/2022, à 19:39
- MicP
Re : Afficher la valeur la plus proche de la moyenne BASH
Oui, je suis sûr qu'avec les fonctions mathématiques superbes d'awk, on pourrait même calculer la moyenne,
et en plus, on pourrait même se passer du shell bash
Mais le titre de ce fil de discussion est : Afficher la valeur la plus proche de la moyenne BASH
Dernière modification par MicP (Le 09/08/2022, à 19:42)
Hors ligne
#12 Le 09/08/2022, à 19:48
- Tawal
Re : Afficher la valeur la plus proche de la moyenne BASH
J'aurais tendance à diriger le demandeur vers un type de solution plus adaptée.
Et en plus question ressource/rapidité, awk s'en sortirai bien mieux que bash dans ce cas là.
Dernière modification par Tawal (Le 09/08/2022, à 19:48)
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#13 Le 09/08/2022, à 20:33
- Watael
Re : Afficher la valeur la plus proche de la moyenne BASH
Les moyennes ne sont pas à calculer …
Dans son message #1, VroumH a écrit :… J'ai besoin d'aide, j'ai deux listes
fichier1
…
et j'ai les moyens
fichier2
……puisqu'elles sont données dans fichier2
c'est évidemment très maladroit, puisque lorsque le fichier "source" changera, il faudra calculer en externe les moyennes.
considérons qu'on a un seul fichier de données, et que les moyennes sont à calculer dans le script.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#14 Le 09/08/2022, à 23:07
- MicP
Re : Afficher la valeur la plus proche de la moyenne BASH
…considérons qu'on a un seul fichier de données, et que les moyennes sont à calculer dans le script. …
Une ébauche d'algorithme pour le calcul de la moyenne en pur bash :
nbrBits=$(while [[ $((valeurBin**exposant)) -gt 0 ]]; do $((exposant=exposant+1)); done; echo $((exposant))) # il y a un bit qui est utilisé pour le signe (positif ou négatif)
maxValuePosBash=$(((2**nbrBits)-1)); maxValueNegBash=$((2**nbrBits))
echo "Sur cette machine et avec ce système d'exploitation, bash peut utiliser un entier signé allant de $maxValueNegBash à +$maxValuePosBash"
Il faudra que chacune des valeurs et la somme des valeurs restent dans ces limites
et que le nombre d'éléments soit inférieur ou égal à la valeur positive maxi : maxValuePosBash
- Extraire du fichier la série des valeurs dont il faudra calculer la moyenne
- Vérifier que le nombre d'éléments est inférieur ou égal à la valeur positive maxi : maxValuePosBash
sinon, c'est cuit => on s'arrête là
Pour transformer chacune des valeurs en entier signé, il faudra :
- Pour chacune des valeurs, s'il n'existe pas de point décimal dans la valeur alors ajouter un point décimal à la fin de la valeur
- Égaliser le nombre de décimales des valeurs en ajoutant au besoin des zéros à la fin
- Supprimer le point décimal dans chaque valeur
- Vérifier que chacune des valeurs reste dans les limites autorisées et ajuster au besoin en ajoutant/supprimant des chiffres à la fin de chacune des valeur
- Vérifier que la somme des valeurs reste dans les limites autorisées et ajuster au besoin en ajoutant/supprimant des chiffres à la fin de chacune des valeur
Je reprendrai ça plus tard…
Dernière modification par MicP (Le 09/08/2022, à 23:13)
Hors ligne
#15 Le 10/08/2022, à 02:52
- Watael
Re : Afficher la valeur la plus proche de la moyenne BASH
ça ne me gêne pas d'utiliser une programme externe pour pallier les limites du shell.
contrairement aux expr, cut, grep, awk... j'utilise sans souci bc, surtout quand je vois les détours et précautions à prendre pour calculer des décimaux.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#16 Le 10/08/2022, à 06:26
- MicP
Re : Afficher la valeur la plus proche de la moyenne BASH
Bonjour
Il faudra aussi préciser dans le sujet ce qu'il faut faire dans les deux cas suivants :
- il se pourrait que le calcul de la moyenne donne un résultat dont le nombre de décimales est infini
il faudra donc que le nombre de décimales à prendre en compte soit définit dans le sujet
- Il se pourrait que la valeur absolue de la différence avec la moyenne donne le même résultat pour plusieurs valeurs
il faudra donc décider de ce qu'il faut faire dans ce cas là
Dernière modification par MicP (Le 10/08/2022, à 06:27)
Hors ligne
#17 Le 10/08/2022, à 13:54
- LeoMajor
Re : Afficher la valeur la plus proche de la moyenne BASH
salut,
valeur approchée,
:~$ python2 -c 'print round(5.76543, 2)'
5.77
:~$ gbs3 -e 'print round(5.76543, -2)'
5,77
:~$ gbs3 -e "dim f as integer[]=[1900, 1923, 1945, 1960, 1956, 1999, 2020 ]: dim sum as float: for i as integer=0 to f.max: sum+=f[i]: next: print sum/f.count,round(sum/f.count), round(sum/f.count,2),round(sum/f.count,1), round(sum/f.count,-1), round(sum/f.count,-5)"
1957,57142857143 1958 2000 1960 1957,6 1957,57143
:~$ gbs3 -e "dim f as float[]=[-30.133, -6.576, -6.293, -12.034, -7.076]: dim sum as float: for i as integer=0 to f.max: sum+=f[i]: next: print sum/f.count,round(sum/f.count), round(sum/f.count,2), round(sum/f.count,1), round(sum/f.count,-1), round(sum/f.count,-3)"
-12,4224 -12 0 -10 -12,4 -12,422
edit: la valeur de la liste la plus proche de la moyenne
:~$ gbs3 -e "dim f as float[]=[6.024, 3.2, 5.6487, 65.2, 23.23548, 15.34]: dim moy as float: for i as integer=0 to f.max: print i,f[i]: moy+=f[i]: next: moy=round(moy/f.count,-5): print moy,\"moyenne\": f.add(moy): f.sort(): dim sup as float=(f[f.find(moy)+1] -f[f.find(moy)]): dim inf as float=(f[f.find(moy)] -f[f.find(moy)-1]): print if(sup>inf, \"+ proche \" & f[f.find(moy)-1], \"+ proche \" & f[f.find(moy)+1]) "
0 6,024
1 3,2
2 5,6487
3 65,2
4 23,23548
5 15,34
19,7747 moyenne
+ proche 23.23548
Dernière modification par LeoMajor (Le 10/08/2022, à 17:17)
Hors ligne
#18 Le 16/08/2022, à 12:35
- VroumH
Re : Afficher la valeur la plus proche de la moyenne BASH
Merci de tous vos conseils
Hors ligne