IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

troncage d'un montant avec floor et écart de centime.


Sujet :

JavaScript

  1. #41
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    j'espère qu'avec ça, j'aurai droit à ma place dans les "sources js" ?

    voici une version un peu plus compacte (1.2ko)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    function calc(expression,v,i){
      function add(n1,n2){
        var i,len1,len2,len = Math.max(len1=((i= n1.toString().split('.')[1])?i.length:0),len2=((i = n2.toString().split('.')[1])?i.length:0)),zero = '0';
        for(i=1;i<len;i*=2)	zero += zero;
        var result = (parseInt(n1.toString().replace('.',''),10)*Math.pow(10,len-len1)+parseInt(n2.toString().replace('.',''),10)*Math.pow(10,len-len2)).toString();
        result = (Number(result)<0)?('-'+zero+result.substring(1,result.length)):(zero+result);
        return Number(result.substr(0,result.length-len)+'.'+result.substr(result.length-len,result.length));
      }
      function multi(n1,n2){
        var i,len = ((i = n1.toString().split('.')[1])?i.length:0) + ((i = n2.toString().split('.')[1])?i.length:0),zero = '0';
        for(i=1;i<=len;i*=2) zero += zero;
        var result =  (parseInt(n1.toString().replace('.',''),10)*parseInt(n2.toString().replace('.',''),10)).toString();
        result = Number(result)<0?'-'+zero+result.substring(1,result.length):zero+result;
        return Number(result.substr(0,result.length-len)+'.'+result.substr(result.length-len,result.length));
      }
      while(expression != (expression = expression.replace(/\([^\(\)]*\)/,function(a){ var r=calc(a.slice(1,a.length-1));return r;})));
      if((v = expression.split('+')).length>1 && !(expression = 0)){
        for(i=0;i<v.length;i++)
          expression = add(expression,calc(v[i])); 
      }
      if((v = expression.toString().split('*')).length>1 && (expression = 1)){
        for(i=0;i<v.length;i++)
        expression = multi(expression,calc(v[i])); 
      }
      return eval(expression);
    }
    et la version compressée (1ko) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function calc(b,v,i){function y(a,b){var d,i,e,f,g=Math.max(e=((i=a.toString().split('.')[1])?i.length:0),f=((i=b.toString().split('.')[1])?i.length:0)),z="0";for(i=1;i<g;i*=2)z+=z;d=(parseInt(a.toString().replace('.',''),10)*Math.pow(10,g-e)+parseInt(b.toString().replace('.',''),10)*Math.pow(10,g-f)).toString();d=(Number(d)<0)?('-'+z+d.substring(1,d.length)):(z+d);return Number(d.substr(0,d.length-g)+'.'+d.substr(d.length-g,d.length))}function x(a,b){var d,i,g=((i=a.toString().split('.')[1])?i.length:0)+((i=b.toString().split('.')[1])?i.length:0),z="0";for(i=1;i<=g;i*=2)z+=z;d=(parseInt(a.toString().replace('.',''),10)*parseInt(b.toString().replace('.',''),10)).toString();d=Number(d)<0?'-'+z+d.substring(1,d.length):z+d;return Number(d.substr(0,d.length-g)+'.'+d.substr(d.length-g,d.length))}while(b!=(b=b.replace(/\([^\(\)]*\)/,function(a){return calc(a.slice(1,a.length-1))})));if((v=b.split('+')).length>1&&!(b=0))for(i=0;i<v.length;i++)b=y(b,calc(v[i]));if((v=b.toString().split('*')).length>1&&(b=1))for(i=0;i<v.length;i++)b=x(b,calc(v[i]));return eval(b)}
    et la version "packed" (0.9 ko):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(function(a,c){return a.replace(new RegExp('\\b\\d+\\b','g'),function(x){return c[x]||x})}("4 5(b,v,i){4 y(a,b){var d,i,e,f,g=6.max(e=((i=a.7().8('.')[1])?i.9:0),f=((i=b.7().8('.')[1])?i.9:0)),z='0';10(i=1;i<g;i*=2)z+=z;d=(11(a.7().12('.',''),3)*6.pow(3,g-e)+11(b.7().12('.',''),3)*6.pow(3,g-f)).7();d=(13(d)<0)?('-'+z+d.14(1,d.9)):(z+d);15 13(d.16(0,d.9-g)+'.'+d.16(d.9-g,d.9))}4 x(a,b){var d,i,g=((i=a.7().8('.')[1])?i.9:0)+((i=b.7().8('.')[1])?i.9:0),z='0';10(i=1;i<=g;i*=2)z+=z;d=(11(a.7().12('.',''),3)*11(b.7().12('.',''),3)).7();d=13(d)<0?'-'+z+d.14(1,d.9):z+d;15 13(d.16(0,d.9-g)+'.'+d.16(d.9-g,d.9))}while(b!=(b=b.12(/\\([^\\(\\)]*\\)/,4(a){15 5(a.slice(1,a.9-1))})));if((v=b.8('+')).9>1&&!(b=0))10(i=0;i<v.9;i++)b=y(b,5(v[i]));if((v=b.7().8('*')).9>1&&(b=1))10(i=0;i<v.9;i++)b=x(b,5(v[i]));15 eval(b)}",'0|1|2|10|function|calc|Math|toString|split|length|for|parseInt|replace|Number|substring|return|substr'.split('|')));



    nb: ma version compressée possède 3 variables locales "b" et "v" et "i", évitez donc les appels du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var b=2, v=3;
    calc('b+v');
    et préférez :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var b=2, v=3;
    calc('self.b+self.v');
    ou encore

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var b=2, v=3;
    calc(b+'+'+v);
    ou plus simplement évitez de nommer vos variables "b" et "v" et "i" lors des appels à la fonction calc.

    edit: nouvelle erreur des négatif corrigée !

  2. #42
    Membre Expert
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Par défaut
    Sinon on peut "poser" la multiplication comme à l'école :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
       53.45
    *   12.3
    ________
       16035
    + 106900
    + 534500
    ________
     657.435
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    function numberToString(x) {
    	var xString = String(x);
    	if (xString.match(/^[+-]?\d+(?:.\d+)?$/)) {
    		return xString;
    	} else if (xString.match(/^([+-]?\d+(?:.\d+)?)e-(\d+)$/)) {
    		var num = RegExp.$1;
    		var dec = RegExp.$2;
    		var res = "0.";
    		for (var i = 1; i < dec; i++) {
    			res += "0";
    		}
    		res += num.replace(".", "");
    		return res;
    	}
    	else
    		return "NaN";
    }
     
    function mult(x, y){
    	var xString = numberToString(x);
    	var yString = numberToString(y);
    	var xDecCount = (xString.indexOf(".") > -1) ? xString.length - 1 - xString.indexOf(".") : 0;
    	var yDecCount = (yString.indexOf(".") > -1) ? yString.length - 1 - yString.indexOf(".") : 0;
    	var xArray = xString.replace(/[.+-]/g, "").split("");
    	var yArray = yString.replace(/[.+-]/g, "").split("");
    	var subResults = new Array();
    	var retain;
    	// Multiplication
    	var index = 0;
    	for (var i = xArray.length - 1; i >= 0; i--) {
    		subResults[index] = "";
    		// Ajout des 0 devant chaque nouvelle "ligne"
    		for (var z = 0; z < index; z++) {
    			subResults[index] += "0";
    		}
    		var retain = 0;
    		for (var j = yArray.length - 1; j >= 0; j--) {
    			var res = (xArray[i] * yArray[j]) + retain;
    			retain = Math.floor(res / 10);
    			subResults[index] = String(res % 10) + subResults[index];
    		}
    		if (retain > 0) {
    			subResults[index] = String(retain) + subResults[index];
    		}
    		index++;
    	}
     
    	var maxSize = 0;
    	for(var i = 0; i < subResults.length; i++) {
    		if (maxSize < subResults[i].length + i) {
    			maxSize = subResults[i].length;
    		}
    	}
     
    	// Addition finale
    	var result = "";
    	var subRes;
    	retain = 0;
    	for (var j = 0; j < maxSize; j++) {
    		subRes = 0;
    		for (var i = 0; i < subResults.length; i++) {
    			var index = subResults[i].length - 1 - j;
    			if (index > -1) {
    				subRes += Number(subResults[i][index]);
    			}
    		}
    		subRes += retain;
    		retain = Math.floor(subRes / 10);
    		result = String(subRes % 10) + result;
    	}
     
    	if (retain < result.length) {
    		result = String(retain) + result;
    	}
     
    	var decIndex = result.length - (xDecCount + yDecCount);
    	if (decIndex > 0) {
    		result = result.substring(0, decIndex) + "." + result.substring(decIndex);
    	}
    	if (x < 0 ^ y < 0) {
    		result = "-" + result;
    	}
     
    	return Number(result);
    }
    J'ai pas testé mais à priori ça ne devrait pas poser de souci (juste des multiplications). Par contre ça ne doit pas être super efficace.

  3. #43
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Je préfère ma solution, allez : avouez qu'elle est canon !

  4. #44
    Membre Expert
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Par défaut
    Ben moi je préfère la mienne

    En plus les instits peuvent l'utiliser (voire les élèves) \o/
    Il suffit d'afficher les sous-résultats et ça fait une multiplication comme à l'école \o/

  5. #45
    Rédacteur/Modérateur

    Avatar de SpaceFrog
    Homme Profil pro
    Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Inscrit en
    Mars 2002
    Messages
    39 661
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2002
    Messages : 39 661
    Billets dans le blog
    1
    Par défaut
    Juste un détail loce ...

    . en regexp c'est le joker

    => \. ou [.]
    Ma page Developpez - Mon Blog Developpez
    Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
    Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
    Votre post est résolu ? Alors n'oubliez pas le Tag

    Venez sur le Chat de Développez !

  6. #46
    Membre Expert
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Par défaut
    Citation Envoyé par SpaceFrog Voir le message
    Juste un détail loce ...

    . en regexp c'est le joker

    => \. ou [.]
    Oui, erreur d'inattention j'ai oublié de l'échapper.

    Au moins t'as lu mon code.

  7. #47
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Citation Envoyé par Loceka Voir le message
    Ben moi je préfère la mienne

    En plus les instits peuvent l'utiliser (voire les élèves) \o/
    Il suffit d'afficher les sous-résultats et ça fait une multiplication comme à l'école \o/
    bah c'est la même solution sur le fait qu'on retire la virgule via le string et puis qu'on la replace après la multiplication entière sauf que toi tu t'amuses à recoder la multiplication au lieu d'utiliser simplement l'opérateur * sur les valeurs.

    et ma fonction corrige également les additions et soustraction flottante et gère les devisions et les parenthèses dans les calculs. c'est juste tout beau tout bien !

  8. #48
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 262
    Par défaut
    j'en mets une autre que j'aime bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function _mul( val1, val2){
      // decomposition
      var valeur1 = val1.toString().split('.');
      var valeur2 = val2.toString().split('.');
      // nombre de decimal a traiter
      var decimal = ( valeur1[1] ? valeur1[1].length : 0);
      decimal    += ( valeur2[1] ? valeur2[1].length : 0);
      // recup les valeurs entiere
      valeur1 = parseInt( valeur1.join(''),10);
      valeur2 = parseInt( valeur2.join(''),10);
      // boucle d'addition
      var i, nb = valeur2 , somme = 0;
      for( i=0; i <nb; i++){
        somme += valeur1;
      }
      return( somme / Math.pow( 10, decimal));
    }
    que des additions...

    J'aime bien celle de Loceka pour son coté très pédagogique.

    [edit]beau boulot quand même Willpower![/edit]

  9. #49
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    j'en mets une autre que j'aime bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function _mul( val1, val2){
      // decomposition
      var valeur1 = val1.toString().split('.');
      var valeur2 = val2.toString().split('.');
      // nombre de decimal a traiter
      var decimal = ( valeur1[1] ? valeur1[1].length : 0);
      decimal    += ( valeur2[1] ? valeur2[1].length : 0);
      // recup les valeurs entiere
      valeur1 = parseInt( valeur1.join(''),10);
      valeur2 = parseInt( valeur2.join(''),10);
      // boucle d'addition
      var i, nb = valeur2 , somme = 0;
      for( i=0; i <nb; i++){
        somme += valeur1;
      }
      return( somme / Math.pow( 10, decimal));
    }
    que des additions...

    J'aime bien celle de Loceka pour son coté très pédagogique.

    [edit]beau boulot quand même Willpower![/edit]

    ça utilise dans une boucle au lieu d'utiliser simplement la multiplication * alors qu'on sait que la multiplication entière ne peut avoir de problème de virgule flottante (logique hein ) donc la mienne reste mieux. (même si mon code est illisible)

  10. #50
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 262
    Par défaut
    dans une boucle au lieu d'utiliser simplement la multiplication * alors qu'on sait que la multiplication entière ne peut avoir de problème de virgule flottante (logique hein ) donc j'aime beaucoup moins.
    bien d'accord avec toi, j'aime beaucoup moins également car aucun test sur le plus grand nombre, donc cela peux mouliner sec, imagine un 0.12 * 1743.521 contre un 1743.521 *0.12.

    Dans tout les cas cette solution, just for fun, est à bannir car potentiellement hyper longue. Je lui préfère celle que j'ai mise en première instance.

  11. #51
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    bien d'accord avec toi, j'aime beaucoup moins également car aucun test sur le plus grand nombre, donc cela peux mouliner sec, imagine un 0.12 * 1743.521 contre un 1743.521 *0.12.

    Dans tout les cas cette solution, just for fun, est à bannir car potentiellement hyper longue. Je lui préfère celle que j'ai mise en première instance.
    ma fonction "multi" remanier en 2 courtes lignes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function multi(a,b){
        var c = ((a=a.toString().split('.'))[1]?a[1].length:0)+((b=b.toString().split('.'))[1]?b[1].length:0);
        return  parseInt(a.join(''),10)*parseInt(b.join(''),10)/Math.pow(10,c);
    }


    j'vais étendre ce remaniement à ma fonction "calc" (comprenant les 3 autres opérations de base et les parenthèses).

    edit: voici la fonction "add" (addition et soustraction)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      function add(a,b){
        var d,e,c = Math.max(d=(a=a.toString().split('.'))[1]?a[1].length:0,e=(b=b.toString().split('.'))[1]?b[1].length:0);
        return  (parseInt(a.join(''),10)*Math.pow(10,c-d)+parseInt(b.join(''),10)*Math.pow(10,c-e))/ Math.pow(10,c);
      }

  12. #52
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    j'optimiserai le reste de ma fonction "calc" plus tard, voici déjà la version avec "add" et "multi" bien diminués :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function calc(expression){
      var v,i;
      function add(a,b){
        var d,e,c = Math.max(d=(a=a.toString().split('.'))[1]?a[1].length:0,e=(b=b.toString().split('.'))[1]?b[1].length:0);
        return  (parseInt(a.join(''),10)*Math.pow(10,c-d)+parseInt(b.join(''),10)*Math.pow(10,c-e))/ Math.pow(10,c);
      }
      function multi(a,b){
        var c = ((a=a.toString().split('.'))[1]?a[1].length:0)+((b=b.toString().split('.'))[1]?b[1].length:0);
        return  parseInt(a.join(''),10)*parseInt(b.join(''),10)/ Math.pow(10,c);
      }
      while(expression != (expression = expression.replace(/\([^\(\)]*\)/,function(a){ var r=calc(a.slice(1,a.length-1));return r;})));
      if((v = expression.split('+')).length>1 && !(expression = 0)){
        for(i=0;i<v.length;i++)
          expression = add(expression,calc(v[i])); 
      }
      if((v = expression.toString().split('*')).length>1 && (expression = 1)){
        for(i=0;i<v.length;i++)
        expression = multi(expression,calc(v[i])); 
      }
      return eval(expression);
    }

  13. #53
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    version (presque) finale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function add(a,b){
      var d,e,c = Math.max(d=(a=a.toString().split('.'))[1]?a[1].length:0,e=(b=b.toString().split('.'))[1]?b[1].length:0);
      return  (parseInt(a.join(''),10)*Math.pow(10,c-d)+parseInt(b.join(''),10)*Math.pow(10,c-e))/ Math.pow(10,c);
    }
    function multi(a,b){
      var c = ((a=a.toString().split('.'))[1]?a[1].length:0)+((b=b.toString().split('.'))[1]?b[1].length:0);
      return  parseInt(a.join(''),10)*parseInt(b.join(''),10)/ Math.pow(10,c);
    }
    function calc(expression,v){
      // parenthèses
      while(expression != (expression = expression.replace(/\([^\(\)]*\)/,function(a){return calc(a.slice(1,a.length-1))})));
      // additions/soustractions
      if((v = expression.split('+')).length>1)  expression = add(calc(v[0]),calc(v.slice(1).join('+'))); 
      // multiplications
      if((v = expression.toString().split('*')).length>1) expression = multi(calc(v[0]),calc(v.slice(1).join('*'))); 
      // divisions/number(string)
      return eval(expression);
    }
    essayez de faire mieux maintenant !

  14. #54
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    finale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function add(a,b){
      var d,e,c=Math.max(d=(a=a.toString().split('.'))[1]?a[1].length:0,e=(b=b.toString().split('.'))[1]?b[1].length:0);
      return (parseInt(a.join(''),10)*Math.pow(10,c-d)+parseInt(b.join(''),10)*Math.pow(10,c-e))/ Math.pow(10,c);
    }
    function multi(a,b){
      var c=((a=a.toString().split('.'))[1]?a[1].length:0)+((b=b.toString().split('.'))[1]?b[1].length:0);
      return parseInt(a.join(''),10)*parseInt(b.join(''),10)/Math.pow(10,c);
    }
    function calc(expression){ 
      var v,f=calc,c='¨',e=expression;
      while(e!=(e=e.replace(/\([^\(\)]*\)/,function(a){return f(a.slice(1,a.length-1))})));
      if((v=e.replace(/\+/,c).split(c)).length>1)e=add(f(v[0]),f(v[1])); 
      if((v=e.toString().replace(/\*/,c).split(c)).length>1)e=multi(f(v[0]),f(v[1])); 
      return eval(e);
    }

  15. #55
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    mon code ci-dessus peu sembler "abstrait" et pourtant il fonctionne ultra bien !

    batterie de tests qui posaient problèmes (sans mon code) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    document.write( calc("(2+(0.2*0.2))*(0.2/1)"), '<br>'); // 0.408
    document.write( calc("2+0.2*0.2/3"), '<br>'); // 2.013333333333333
    document.write( calc("60*1.196"), '<br>'); // 71.76
    document.write( calc("10*1.18"), '<br>'); // 11.8
    document.write( calc("-0.2-0.05"), '<br>'); // -0.25
    var tier = 1/3;
    document.write( calc("tier*3"), '<br>'); // 1
    for(var i = 0.1; i < 1; i=calc(i+"+0.1"))
    	document.write( i, '<br>'); // 	0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9

  16. #56
    Membre Expert
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Par défaut
    Citation Envoyé par Willpower Voir le message
    on sait que la multiplication entière ne peut avoir de problème de virgule flottante (logique hein )
    Ouaip mais ça peut avoir d'autres problèmes : tu peux très vite atteindre le max des entiers. Alors qu'avec ma solution non, faut atteindre le max des String.

  17. #57
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Citation Envoyé par Loceka Voir le message
    Ouaip mais ça peut avoir d'autres problèmes : tu peux très vite atteindre le max des entiers. Alors qu'avec ma solution non, faut atteindre le max des String.
    10^308 (autrement dit 308 chiffres) !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    alert(Number.MAX_VALUE);
    ce qui me semble suffisament quand on sait que javascript arrondi après ~17 chiffres derriere la virgule.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    alert(0.999999999999999990); // 1

    ----------

    edit : la partie que je trouve vraiment intéressante dans ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	else if (xString.match(/^([+-]?\d+(?:.\d+)?)e-(\d+)$/)) {
    		var num = RegExp.$1;
    		var dec = RegExp.$2;
    		var res = "0.";
    		for (var i = 1; i < dec; i++) {
    			res += "0";
    		}
    		res += num.replace(".", "");
    		return res;
    	}
    ça permettrai d'effectuer des calculs (approximatifs) sur des nombres plus petits que 0.000001, ce qui n'est actuellement pas possible dans ma version.

    cette partie peut d'ailleus être adaptée comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	else if(xString.match(/^([+-]?\d+(?:.\d+)?)e-(\d+)$/))
    	{
    		var num=RegExp.$1, dec=RegExp.$2, zero="0";
    		for (var i = 1; i < dec; i*=2) // max 9 itérations (avec dec=324)
    			zero += zero;		
    		return "0."+zero.substring(0,dec-1)+num.replace(".", "");
    	}
    pour éviter de faire 324 itérations pour xString = Number.MIN_VALUE = 1e^-324



    ------------

    edit: arg !
    j'ai implémenté les calculs sur petites valeurs qui fonctionnent nickels mais ça m'a permis de détecter un nouveau bug :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    document.write(calc("0.000000000000000000000000000001*10000000000000"));
    // -> 0.000000000000000009999999999999999 au lieu de 0.00000000000000001
    à cause de "/Math.pow(10,dec)" dans "multi"

    donc pour certaines valeur, l'imprecision de la division est bien génante !

    je peux corriger ma fonction "multi" en réutilsant ma méthode initiale qui consistait à replacer la virgule de mon résultat via le string au lieu de diviser par "pow(10,position_virgule)".

    mais surtout, je pense que je vais être obligé de coder la fonction "div" maintenant.


    edit: mon code actuel (erreur ci-dessus non corrigée)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    var MAX_ZERO=(function(zero,max,i){for(;i<max;i*=2)zero+=zero;return zero.substring(0,max-1)})("0",Number(Number.MAX_VALUE.toString().split("e")[1]),1);
    function expToString(val){
      if(!val.toString().match(/^([+-]?\d+(?:.\d+)?)e([-\+]?\d+)$/)) return val;
      if(RegExp.$2<0) return "0."+MAX_ZERO.substring(0,-RegExp.$2-1)+RegExp.$1.replace(".", "");
      return RegExp.$1.replace(".", "")+MAX_ZERO.substring(0,RegExp.$2);
    }    
    function add(a,b){
      var d,e,c=Math.max(d=(a=a.toString().split('.'))[1]?a[1].length:0,e=(b=b.toString().split('.'))[1]?b[1].length:0);
      return (parseInt(a.join(''),10)*Math.pow(10,c-d)+parseInt(b.join(''),10)*Math.pow(10,c-e))/ Math.pow(10,c);
    }
    function sub(a,b){
      return add(a,-b);
    }
    function multi(a,b){
      var c=((a=a.toString().split('.'))[1]?a[1].length:0)+((b=b.toString().split('.'))[1]?b[1].length:0);
      return parseInt(a.join(''),10)*parseInt(b.join(''),10)/Math.pow(10,c);
    }
    function calc(expression){ 
      var v,f=calc,c='¨',e=expression;
      while(e!=(e=e.replace(/\([^\(\)]*\)/,function(a){return f(a.slice(1,a.length-1))})));
      if((v=e.replace(/\+/,c).split(c)).length>1)e=add(f(v[0]),f(v[1])); 
      if((v=e.toString().replace(/\*/,c).split(c)).length>1)e=multi(f(v[0]),f(v[1])); 
      return expToString(eval(e));
    }
    document.write(calc("0.000000000000000000000000000001*10000000000000"));

Discussions similaires

  1. smartforms affichage de montants avec signe "-"
    Par kitty2006 dans le forum SAP
    Réponses: 6
    Dernier message: 11/12/2007, 13h55
  2. Problème avec RAID5 sur carte Asus M2N32-SLI Deluxe
    Par Dioxine dans le forum Composants
    Réponses: 8
    Dernier message: 17/08/2007, 08h30
  3. Réponses: 5
    Dernier message: 19/04/2007, 12h45
  4. Capture de fronts montants avec un PIC16F876
    Par sylvain42 dans le forum C
    Réponses: 3
    Dernier message: 12/06/2006, 14h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo