Manipuler de grands nombres

Résolu/Fermé
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 - Modifié le 9 oct. 2022 à 23:48
yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024 - 23 oct. 2022 à 23:03

Bonjour,

J'ai un exercice très long dans lequel on me demande de manipuler de grands entiers. Je n'arrive pas à faire le début de l'exercice et donc il est m'est impossible de faire le reste.

Je veux juste comprendre le début pour bien démarrer et ensuite je pourrais faire la suite (du moins j'espère).Votre aide me sera précieuse

On m'a donné ceci et il faut que je le complète :

tall_integer *ge_cree(void) {
  return NULL;
}

void free(tall_integer *e) {
}

tall_integer *set_bit(tall_integer *e, uint32_t x) {
  return NULL;
}

tall_integer *clr_bit(tall_integer *e, uint32_t x) {
  return NULL;
}

char get_bit(tall_integer *e, uint32_t x) {
  return 0;
}

int nb_bits(tall_integer *e) {
  return 0;
}

tall_integer *add(tall_integer *b, tall_integer *a) {
  return NULL;
}

tall_integer *shift(tall_integer *a, int nb_bits) {
  return NULL;
}

tall_integer *mul(tall_integer *b, tall_integer *a) {
  return NULL;
}

La question 1 concerne les fontions creer et liberer .

Pour creer, on me demande de créer dans le tas un grand entier de 32 bits débutant à la valeur 0 et de renvoyer un pointeur sur ce dernier. La fonction renvoie NULL si l'entier n'a pas pu être créé.

Pour liberer, c'est pour juste libérer l'entier créé. 

Mon problème surtout est qu'on me demande de définir moi même le type tall_integer et c'est ça mon problème et qui m'empêche d'avancer et comment créer un entier

Pour libérer je suppose que je dois juste mettre free(...)

...=entier à libéré

Moi je pensais en C il fallait juste écrire int entier et hop on a créé un entier mais vu les questions de mon exercice je me dis que ça doit pas être ça qu'on me demande...

27 réponses

Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
17 oct. 2022 à 13:21

Bon comme cela depend du resulatat a obtenir et de k methode choisi,le mieux donc est que je reviens sur mon exo de base.Peut etre si je le comprends je pourrais aussi le faire pour des petits entiers

la fonction add ajoute au grand nombre pointe par b la valeur du grand nombre pointe par a donc *b=*b+*a et doit me renvoyer b


Alors aidez moi a trouver une methode car moi a part utiliser le xor ou le et je sais pas comment m'y prendre.J'ai beau essayer j'arrive pas

yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024 1 495
17 oct. 2022 à 15:06

Dans quel contexte fais-tu cela?

Si tu veux progresser, peut-être préférable de faire d'abord des exercices à ton niveau.

0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
17 oct. 2022 à 15:20

Dans aucun contexte du moins je pense

mon exo  a 3 grande parties

1.Gerer la memoire des entiers(créé et libéré un grand entier)

Partie que on m'a deja aidé

2.Manipuler des bits

Set bit=met a 1 le bit de position x dans le grand entier pointe par e et renvoie e

clear bit=met  a 0 .....

get bit doit me renvoyer ka valeur du bit de position x dans le grand entier pointe par e

nb_bit doit me donner le nombre de bit du grand entier pointe par e

3.On veut que je fais de l'arithmetique sur de grands nombres

a savoir addition,multiplication et decalage

En gros j'ai resume ce qu'on me demande de faire

Vu que on m'a donne ça en devoir ça veut dire que je dois etre capable de le faire

yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024 1 495
17 oct. 2022 à 15:26

Ah, il s'agit d'un devoir, c'est cela le contexte.

N'est-ce pas un travail personnel, donc à faire seul?

Je suggère de progresser avec des exercices plus simples, et de faire ce devoir ensuite.

0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1 > yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024
17 oct. 2022 à 15:50

C'est un devoir oui mais mon prof a dit vu que c'est un exi assez difficile,vois pouvez demander de l'aide

Je voulais le faire seul mais vraiment je suis rester longtemps bloqué sans avancer du coup j'avais besoin d'aide vu que je dois le finir cette semaine 

0
yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024 1 495 > Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023
17 oct. 2022 à 15:55

Tu as fait la partie 1?

Tu as une question sur la partie 2?

0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1 > yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024
17 oct. 2022 à 19:39

mamiemando et Dal m'ont aidé pour cette partie à comprendre apres j'essaierais de le faire moi même

0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 088
Modifié le 17 oct. 2022 à 16:00

Je pense que Theo_0055 devrait être intéressé par ce code d'exemple présenté sur la page Wikipedia des opérateurs bit à bits du C :

https://en.wikipedia.org/wiki/Bitwise_operations_in_C#Example:_a_simple_addition_program

L'idée est d'identifier les cas où la retenue est nécessaire (c'est à dire là où à la même position tu as 1 et 1 à un moment donné dans la même colonne) avec l'opérateur &.

L'exemple ne fonctionne que sur un type standard du C, mais cela devrait lui donner une idée de comment gérer les retenues au niveau du bit... si le but de l'exercice est vraiment de faire des opérations de ce type sans utiliser les opérateurs du C (j'ai présenté une méthode alternative utilisant les opérateurs du C et gérant la retenue pour des blocs entiers de uint32_t).

Si, donc, tu dois bien travailler au niveau du bit, l'exemple de Wikipedia serait à extrapoler pour fonctionner avec un tableau de données du type choisi, en poursuivant la propagation des retenues et la poursuite des calculs sur les données dans les cellules suivantes du tableau.

Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
17 oct. 2022 à 19:43

 Merci beaucoup ça m'a pris du temps avant de comprendre l'addition sur wikipédia

Votre méthode pour gérer les retenues est facile a comprendre mais pour l'addition cela suppose que on dépasse la valeur maximale de uint32(INT32_MAX) mais si on additionne des nombres petits exemple 2 et2 on aura jamais le cas ou ça dépasse UINT32_MAX

Merci je vais essayer

0
mamiemando Messages postés 33173 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 10 juillet 2024 7 761
17 oct. 2022 à 16:13

Bonjour,

@all

Pour commencer, je pense que les personnes qui participent aux réponses n'inondent le fil de discussion en donnant de petits indices. Je conçois que ça a un intérêt pédagogique, et ce serait parfait dans une salle de cours. Je suis également d'accord sur le fait qu'on ne veut pas faire les exercices des étudiants à leur place. Le problème c'est que cela conduit à des fils de discussions complètement illisibles.

Donc ce que je propose, c'est que vous ayez ce genre d'échanges via des message privés (sous réserve bien sûr que la personne qui a posé le problème ait un compte CCM, sinon ça va être compliqué de lui envoyer des messages privés).

Il faut en particulier garder à l'esprit que d'autres internautes peuvent être intéressés par cette discussion mais ne seront pas intéressés par ces échanges.

@Theo_0055 StatutMembre

Retour au problème

Raisonne octet par octet. Si tu sais faire une addition sur un octet et que tu sais propager une retenue, alors tu sauras faire une addition sur plusieurs octets.

Il faut donc que cette fonction auxiliaire prenne deux uint8_t en paramètre, retourne leur addition et l'éventuelle retenue.

Si on raisonne sur un bit, l'idée du xor que tu proposes est intéressante (voir message #38) :

  • 0 ^ 0 = 0
  • 0 ^ 1 = 1
  • 1 ^ 0 = 1
  • 1 ^ 1 = 0 (mais ici il ne faut pas oublier la retenue)

Si on raisonne sur un octet par contre, il faut que l'on propage à chaque fois l'éventuelle retenue. Par exemple, en binaire, il faut s'assurer que 01111111 + 00000001 = 10000000.

On s'aperçoit donc qu'il faut aussi être capable d'extraire le i-ème bit d'un octet. Cela a été évoqué dans plusieurs messages de cette discussion, tu extraies le i-ème bit d'un octet x en appliquant un ET logique avec un octet faisant office de masque, tel que dans cet octet, seul le i-ème bit vaut 1. Si après application de ce ET logique, le résultat est nul, alors c'est que le i-ème bit de x était nul, sinon il était égal à 1.

uint8_t bit_5 = ((x & (i << 5)) != 0);

Selon ce principe on peut écrire une fonction pour afficher un buffer en binaire.

#include <stdio.h>
#include <stdint.h>

uint8_t get_ith_bit(const uint8_t * buffer, size_t bit_index) {
    uint8_t byte = buffer[bit_index / 8];
    return (byte & (1 << (bit_index % 8))) != 0;
}                      

void print_bin(const uint8_t * buffer, size_t size) {
    for (size_t i = 0; i < 8 * size; ++i) {
        size_t i_rev = 8 * size - i - 1;
        printf("%d", get_ith_bit(buffer, i_rev));
    }               
}                   
                    
int main() { 
    uint32_t x = 78;
    print_bin((const uint8_t *) &x, sizeof(x));
    printf("\n");
    return 0;       
}

Nommons x et y les deux opérandes (de type tall_int) de l'addition.

Si maintenant, on est capable d'extraire le i-ème bit d'un buffer de taille arbitraire (ici depuis un buffer de 32 bits dans mon extrait de code précédent) alors on est capable :

  • d'extraire le i-ème bit de x
  • d'extraire le i-ème bit de y
  • de déduire avec xor quel sera le ième bit du résultat de l'addition (c'est ce que tu as proposé)
  • de déduire si le i-ème bit des de x et y vaut 1, s'il faut propager une retenue
retenue = get_ith_bit(x, i) && get_ith_bit(y, i);

Pour modifier le i-ème bit d'un buffer, on suit le même raisonnement que pour get_ith_bit, mais on modifie en place le buffer en lui appliquant un OU logique avec le masque adéquat.

#include <stdio.h>
#include <stdint.h>

uint8_t get_ith_bit(const uint8_t * buffer, size_t bit_index) {
    uint8_t byte = buffer[bit_index / 8];
    return (byte & (1 << (bit_index % 8))) != 0;
}                      

void print_bin(const uint8_t * buffer, size_t size) {
    for (size_t i = 0; i < 8 * size; ++i) {
        size_t i_rev = 8 * size - i - 1;
        printf("%d", get_ith_bit(buffer, i_rev));
    }               
}                   

void set_ith_bit_to_0(uint8_t * buffer, size_t bit_index) {
    buffer[bit_index / 8] &= ~(1 << (bit_index % 8));
}

void set_ith_bit_to_1(uint8_t * buffer, size_t bit_index) {
    buffer[bit_index / 8] |= (1 << (bit_index % 8));
}

void set_ith_bit(uint8_t * buffer, size_t bit_index, uint8_t zero_or_one) {
    if (zero_or_one == 0) {
        set_ith_bit_to_0(buffer, bit_index);
    } else {
        set_ith_bit_to_1(buffer, bit_index);
    }
}
                    
int main() { 
    uint32_t x = 0;
    uint8_t * buffer = (uint8_t *) &x;
    print_bin(buffer, sizeof(x));
    printf("\n");
         
    set_ith_bit(buffer, 7, 1);
    print_bin(buffer, sizeof(x));
    printf("\n");
         
    set_ith_bit(buffer, 7, 0);
    print_bin(buffer, sizeof(x));
    printf("\n");
    return 0;
}

À toi ensuite d'écrire la boucle qui va réaliser l'addition. Pour faire simple je te conseille de considérer que x et y font la même taille en mémoire. Pour chaque valeur de i allant de 0 à 8 *sizeof(x), tu extrais le i-ème bit de x et y, fait le xor de ces deux opérandes, puis fait le xor de ce résultat avec la retenue, et en déduis le i-ème bit du résultat et son éventuelle retenue.

Si quand tu arrives au dernier bit, il te reste une retenue a propagé, c'est que la somme des deux entiers dépasse la valeur maximale qu'il est impossible d'encoder dans ton tall_int. C'est un problème parfaitement "normal" qui se pose avec des entiers standards aussi (voir cette discussion). Je ne sais pas ce que ton exercice attend dans ce genre de situation, mais en C++ il faudrait lever une exception, et en C, probablement quitter le programme avec exit après avoir affiché un message d'erreur.

Bonne chance

yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024 1 495
17 oct. 2022 à 17:42

Je pensais que la charte décourageait l'aide via des message privés.

Peut-être préférable, alors, de proposer de migrer la discussion vers un autre forum, plus approprié?  Une suggestion?

2
georges97 Messages postés 12090 Date d'inscription lundi 31 janvier 2011 Statut Contributeur Dernière intervention 13 juillet 2024 2 309 > yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024
Modifié le 17 oct. 2022 à 18:02

Bonjour,

Je m'oppose également que les MP servent et deviennent comme cela ne manquerait pas de se produire de moyen de manifester sa volonté affirmée de ne pas respecter les règles du forum ou à transposer à l'abri d'un anonymat bien permissif des interpellations irrespectueuses en vigueur sur les réseaux dits sociaux.
 

C'est grâce à des échanges parfois confus mais oh combien instructifs que j'ai pu pour ma part progresser dans la découverte des arcanes de la programmation.
 

Il est vrai que sur d'autres forums, le contrôle strict des dérives garantit que l'on ne divague pas au gré des velléités libertaires de certains visiteurs vindicatifs.

3
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 088 > georges97 Messages postés 12090 Date d'inscription lundi 31 janvier 2011 Statut Contributeur Dernière intervention 13 juillet 2024
17 oct. 2022 à 19:18

A titre personnel, je ne suis pas pour non plus. Je comprends aussi le souci de mamiemando en tant que modératrice de vouloir conserver une lisibilité aux fils, surtout que la question posée est intéressante et la réponse pourrait servir à d'autres à l'avenir. Il me semble qu'il y a des outils sur CCM pour faire cela : en plussant le contenu le plus pertinent pour qu'il remonte et se retrouve à proximité de la question.

Cela dit, là le topic bascule en discussion hors sujet pour le pauvre Theo_0055... à savoir les "discussions visant à faire avancer la réflexion des PO doivent-elles être être traitées en MP ou pas" et peut-être que s'il faut avoir une discussion sur ce sujet là, il faudrait créer un autre topic dans un forum différent, ou en discuter en MP. J'invite mamiemando à ouvrir un topic sur un forum approprié et nous y inviter par MP si elle pense que cela mérite une discussion ouverte.

@Theo_0055 StatutMembresi tu as des questions sur le code posté par mamiemando dans son message ou le code dont j'ai donné le lien sur Wikipedia ou sur un autre échange ou autre chose en lien avec ton sujet, n'hésite pas ignorer cette sous-discussion et à poster :-)

@mamiemando StatutModérateuras-tu vu mon MP ?

0
georges97 Messages postés 12090 Date d'inscription lundi 31 janvier 2011 Statut Contributeur Dernière intervention 13 juillet 2024 2 309 > [Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024
17 oct. 2022 à 19:29

Tout à fait d'accord avec toi, Dal, sur la totalité de ton post. Je ne voulais surtout pas perturber ce fil assurément dense et un peu complexe. Désolé pour mon intrusion un peu intempestive, en souvenir de quelques MP agressifs de visiteurs heureusement disparus dans le cyber*espace.

J'en profite pour exprimer tout le respect que j'ai pour le travail pédagogique accompli par mamiemando, que je suis fidèlement.

Bonne soirée à tous

0
mamiemando Messages postés 33173 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 10 juillet 2024 7 761 > Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023
18 oct. 2022 à 16:48

Bonjour,

Réponse globale pour les messages #60 à #67

J'aimerais revenir sur mon message #59 qui visiblement a suscité beaucoup d'émotions. Avant toute chose il est primordial que vous compreniez tous que je ne fais de reproche à personne et que j'apprécie tous vos messages. Les questions sont bonnes. Les indices sont bons. Les solutions sont bonnes. Mon but n'est nullement d'opérer à une forme de censure, surtout comme quand je viens de le dire, le contenu en lui-même des messages est bon.

Le problème c'est quand une question simple engendre plein de questions en cascade et plein de discussion en cascade et mène à un fil de discussion qui traite de plusieurs problèmes. Mais je pense que nous avons tous le même objectif : aider des gens (pour les intervenants) et trouver de l'aide (pour les gens qui posent des problèmes). Pour être efficaces sur ces deux angles, le but est d'avoir un forum aussi lisible que possible. Pour cela il faut respecter autant que possible deux règles :

  • définir un problème bien délimité dans un fil de discussion : donc bien formuler sa question, avec un exemple minimal, ce qu'on a essayé de faire, comme le suggèrent cette page et cette page.
  • en cas de dérive :
    •  en tant que personne qui pose des questions, il faut autant que possible se discipliner à ouvrir une nouvelle discussion dans le forum adéquat
    • en tant qu'intervenant, inviter la personne à le faire (c'est quelque chose que je fais pour ma part fréquemment).

Donc en réalité [Dal] a très bien dit les choses dans son message #61.

  • Tant qu'on reste dans le sujet initial pourquoi pas.
  • Ici, on empile de nouvelles questions à chaque fois. C'est ce point précis qui m'a fait réagir.

Un point hyper important : j'ai un profond respect pour toutes vos interventions. Mon message n'avait qu'un seul but : améliorer la lisibilité du forum, afin que notre travail à tous soit le plus exploitable possible et le mieux mis en valeur. Je vous prie donc de voir mon message comme un conseil bienveillant, et pas comme une réprimande.

#60 Je n'ai pas vu cette règle. Sans prétendre tout faire correctement, voici comment je procède :

  • Quand j'ai un échange que j'estime intéressant avec quelqu'un, mais pas l'ensemble des internautes, je fonctionne en message privés. C'est assez rare en pratique.
  • Si je reçois des questions en privé pour des problèmes qui méritent d'être posés sur le forum, je réoriente la personne vers le forum, car effectivement les messages privés sont inadaptés.

Ici j'ai évoqué l'idée de MP car j'ai eu la sensation qu'on était plus proche d'un coaching (très bon soit dit en passant) mais qui ne bénéficie, et donc qu'on était plus proche d'une discussion privée. Ces échanges ont de la la valeur pour Théo, ils en ont moins pour quelqu'un qui tombe sur la discussion et qui vient à la recherche d'une solution pour le problème initial.

Mais j'entends aussi le contre argument  de georges sur cette question que ces échanges ont leur intérêt. Du coup la frontière entre échanges privés et publics est un peu flou, et c'est pourquoi je n'ai pas de solution absolue à proposer. Je pense que c'est plus à chacun de se discipliner de sorte à s'assurer qu'on reste dans chaque discussion dans les clous.

#61 Je n'ai rien contre distiller des indices tant que ça reste dans les limites du raisonnable et cantonné au sujet initial.

#62 Je pense que tu as bien résumé pourquoi j'ai écrit mon message #59 dans ce cas précis. 

#63 Tes remarques sont prises dans le bon sens, rassure-toi :-) Et ton point de vue a son importance, donc tu as bien fait de nous en faire part. J'en profite pour te remercier pour ton compliment, qui me va droit au cœur, et que je retourne également aux personnes qui interviennent fréquemment pour leur aide (je pense en l'occurrence, puisqu'ils sont dans cette discussion, à yg_be et [Dal] pour leur fréquentes discussion, et plus largement toutes les personnes qui donnent de leur temps pour proposer leur aide).

#67 Comme je l'expliquais en préambule de ce message, tu dois simplement te discipliner à créer une discussion par problème. Tu peux t'inspirer des questions posées sur stackoverflow pour voir comment formuler idéalement une question.

#66 Il n'y a pas de mauvaises questions, et tu ne dois pas te limiter dans tes questions par rapport à ma remarque. Ce n'est pas le but. Je demandais juste à ce qu'on essaye de faire un fil de discussion par problème. Mais effectivement peut être que comme ta question n'est plus "comment déclarer un type tall_int" mais "comment faire une addition de deux entiers stockés dans un buffer de taille arbitraire", cela mériterait de démarrer une nouvelle discussion, en montrant ce que tu as commencé à faire (par exemple en réutilisant les fonctions que je t'ai proposées).

Bonne chance

2

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
18 oct. 2022 à 17:45

Ok merci je comprends.En fait je me suis dit vu que c'est 1 seul exo avec tous les codes que j'ai presente au debut de la conversation pas la peine de crer un autre sujet vu que en quelque sorte moi je devais implemanter toutes ces fonctions.

Pour se faire il fallait que je definisse le type tall_int,la base sans cela je pouvais pas avancer

merci j'ai regarde votre code,je l'analyse toujours jusqu'a ce que je comprends pour enfin donner une bonne implementation qui marche

Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
20 oct. 2022 à 13:05

@all

Merci pour  tout oh vos retours????,ça m'a beaucoup aide a avancer et a comprendre.

Je pense que c'est bon,on a repondu a mes questions et de toute facon si j'en ai d'autres je créerai un autre sujet 

Merci ????

Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
23 oct. 2022 à 19:45

Bonjour je voulais savoir si je passe de 32 a 1024 bit comment modifier les fonctions suivantes svp

grand_entier_t *ge_set_bit(grand_entier_t *e, uint32_t x) {
     //e->size=4;
    e->data[x/32] |= (1 << (x % 32));
    return e;
}


grand_entier_t *ge_clr_bit(grand_entier_t *e, uint32_t x) {
     //e->size=4;
    e->data[x/32] &= ~(1 << (x% 32));
   
    return e;
}


char ge_get_bit(grand_entier_t *e, uint32_t x) {
   //e->size=4;
  return (e->data[x/32] >> (x%32)) & 1;// return (e->data[x/32] & (1 << (x % 32)))
  
}

int ge_nb_bits(grand_entier_t *e) {
  
  return e->size*32;
}
yg_be Messages postés 22964 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 juillet 2024 1 495
23 oct. 2022 à 23:03

C'est le cœur même de ton exercice.

0