[RUBY] Le nombre de chiffres peut-il être Math.log10 (x) .floor + 1?

Cet article suppose Ruby, mais je pense que la même chose peut être dite pour de nombreuses langues.

Qu'est-ce que tu racontes?

Il existe de nombreuses façons de savoir combien de chiffres un entier positif «x» aura en décimal. L'un d'eux

Math.log10(x).floor + 1

Cependant, est-il vraiment possible d'obtenir la bonne réponse? Même si vous n'êtes pas bon en maths, je vais l'examiner aussi attentivement que possible afin que vous puissiez le comprendre même si vous ne savez pas grand chose sur Ruby.

Cependant, si vous voulez juste connaître la conclusion, [Est-ce que ça va? ](#% E3% 81% 9D% E3% 82% 8C% E3% 81% A7% E3% 81% 84% E3% 81% 84% E3% 81% AE% E3% 81% 8B) ..

Différentes façons de trouver le nombre de chiffres

Dans cette section, on suppose que la variable locale «x» se voit attribuer un entier positif. Ruby peut gérer n'importe quel grand entier si les conditions telles que la mémoire le permettent.

Stringification

Pour les entiers Ruby (classe Integer), générez une chaîne de nombres exprimés en notation N-aire [Integer # to_s](https://docs.ruby-lang.org/ja/2.7.0/method/Integer/i Il existe une méthode appelée /inspect.html).

Si vous omettez l'argument, vous obtenez une chaîne de nombres décimaux.

p (36 + 72).to_s # => "108"

D'autre part, la classe String a une méthode appelée String # length qui compte la longueur (nombre de caractères). Il y a.

p "Ruby".length # => 4

Si vous combinez cela

x.to_s.length

Vous pouvez obtenir le nombre de chiffres avec. C'est assez simple.

Cependant, je me sens un peu mal à l'aise. N'est-il pas lent de créer une énorme chaîne d'une longueur de 100 000 pour un entier de 100 000 chiffres lorsque vous voulez simplement connaître le nombre de chiffres? C'est en fait assez rapide, mais laissons cette histoire de côté.

Obtenez un tableau de nombres chiffre par chiffre

Ruby renvoie un tableau du nombre de chaque chiffre lorsqu'un entier non négatif (un entier supérieur ou égal à 0) est exprimé en notation N-aire Integer # digits Il existe une méthode appelée /2.7.0/method/Integer/i/digits.html).

Si l'argument est omis, il est en notation décimale.

p 1234.digits # => [4, 3, 2, 1]

Puisqu'ils sont disposés dans l'ordre à partir du bas, l'ordre d'apparition est inversé.

Si vous utilisez ceci et Array # length qui renvoie la longueur du tableau

x.digits.length

Vous pouvez obtenir le nombre de chiffres avec.

Mystery était l'idée d'un amateur, "D'une manière ou d'une autre, les entiers semblent être plus rapides que les chaînes de caractères, alors pourquoi ne pas être plus rapide que x.to_s.length?", Mais ce n'était pas le cas. C'est vrai. Un énorme tableau est créé.

Et Math.log10 (x) .floor + 1

Il existe d'autres moyens, mais le sujet principal

Math.log10(x).floor + 1

Allons à. Pourquoi cela me donne-t-il le nombre de chiffres dans «x»?

Math.log10 est une méthode qui renvoie la valeur de la valeur logarithmique commune de l'argument donné.

Fonction logarithmique commune

y = \log_{10}x

Est une fonction exponentielle avec 10 comme base </ ruby>

x = 10^y

C'était la fonction inverse de. Cette fonction exponentielle est facile à comprendre lorsque $ y $ est un entier, mais elle est également définie pour tout nombre réel.

Voyons quand $ y $ est un entier supérieur ou égal à 0

y = \log_{10}x x = 10^y
0 1
1 10
2 100
3 1000
4 10000

À partir de là, on peut voir que lorsque $ y $ est un entier supérieur ou égal à 0, $ y + 1 $, c'est-à-dire que $ \ log_ {10} (x) + 1 $ est le nombre de chiffres.

Cependant, $ x $, où $ y $ est un entier, est limité. Qu'en est-il de l'entier positif le plus courant $ x $?

À titre d'essai, considérez $ x = 999 $. C'est un peu moins de 1000 . Puisque la fonction logarithmique augmente de façon monotone ( y $ augmente à mesure que $ x $ augmente), $ \ log_ {10} 999 $ devrait être ** un peu plus petit ** que $ 3 $. Par conséquent, si vous le convertissez en entier par ** troncature **, vous obtiendrez $ 2 $.

Utilisez la fonction floor Yuka </ ruby> pour la troncature. Cela tronque les cotes à gauche du nombre directement (infini négatif). Dans ce cas, les nombres négatifs n'apparaissent pas, vous pouvez donc le considérer comme "tronquer la partie fractionnaire" [^ fl].

[^ fl]: Notez que pour les nombres négatifs, «-1.1.floor» est «-2», et non «-1» avec la partie fractionnaire tronquée.

À propos, dans les symboles mathématiques, il semble que la fonction de plancher soit écrite comme $ \ lfloor a \ rfloor $, mais à partir de la considération ci-dessus, lorsque $ x $ est de 100 $ ou plus et de 999 $ ou moins,

\lfloor \log_{10}x \rfloor

S'avère être tout 2 $ $. En d'autres termes, cela ressemble à ceci.

x \lfloor \log_{10}x \rfloor
19 0
1099 1
100999 2
10009999 3
1000099999 4

Vous pouvez donc obtenir le nombre de chiffres en ajoutant 1 à $ \ lfloor \ log_ {10} x \ rfloor + 1 $. Mathématiquement.

Est-ce que ça va?

Enfin au cœur.

Si vous écrivez $ \ lfloor \ log_ {10} x \ rfloor + 1 $ en code Ruby

Math.log10(x).floor + 1

Cependant, je me sens un peu mal à l'aise. C'était le but de cet article.

C'est parce que Math.log10 est une opération en virgule flottante de la classe Float. Les opérations en virgule flottante sont généralement accompagnées d'erreurs. Est-il possible que les chiffres résultants soient dans le désordre en raison d'erreurs subtiles?

A quoi dois-je penser?

Où le chiffre change-t-il lorsque l'on regarde l'entier positif «x» dans l'ordre 1, 2, 3, ...? Bien sûr, c'est 9 → 10 ou 99 → 100 ou 999 → 1000. Si une erreur dans une opération de nombre à virgule flottante produit un résultat incorrect, c'est probablement à cette limite. Il est possible que quelque chose comme 10000000 soit par erreur un chiffre de moins, ou quelque chose comme 9999999999 soit fait par erreur un chiffre supplémentaire. Parmi ceux-ci, des nombres tels que 1000000 sont à l'origine sous la forme de $ 10 ^ k $, donc je pense qu'il est peu probable que des erreurs se produisent. Ensuite, expérimentons avec le nombre de 9.

Oui, j'ai écrit ce code.

1.upto(100) do |k|
  puts "%3d %3d" % [k, Math.log10(10 ** k - 1).floor + 1]
end

Changez $ k $ de 1 à 100 pour calculer les chiffres de 10 $ ^ k -1 $ (c'est-à-dire le nombre de 9 arrangés en $ k $). Affichez ceci côte à côte avec $ k $. C'est une correspondance mathématique, alors voyez si les mêmes nombres sont alignés.

Le résultat est le suivant

  1   1
  2   2
  3   3
  4   4
  5   5
  6   6
  7   7
  8   8
  9   9
 10  10
 11  11
 12  12
 13  13
 14  14
 15  16
 16  17
 17  18
 18  19
 19  20
 20  21
 21  22
 22  23
 23  24
 24  25
 25  26
 26  27
 27  28
 28  29
 29  30
 30  31
 31  32
 32  33
 33  34
 34  35
 35  36
 36  37
 37  38
 38  39
 39  40
 40  41
 41  42
 42  43
 43  44
 44  45
 45  46
 46  47
 47  48
 48  49
 49  50
 50  51
 51  52
 52  53
 53  54
 54  55
 55  56
 56  57
 57  58
 58  59
 59  60
 60  61
 61  62
 62  63
 63  64
 64  65
 65  66
 66  67
 67  68
 68  69
 69  70
 70  71
 71  72
 72  73
 73  74
 74  75
 75  76
 76  77
 77  78
 78  79
 79  80
 80  81
 81  82
 82  83
 83  84
 84  85
 85  86
 86  87
 87  88
 88  89
 89  90
 90  91
 91  92
 92  93
 93  94
 94  95
 95  96
 96  97
 97  98
 98  99
 99 100
100 101

C'est hors du milieu. Voici un extrait.

 14  14
 15  16

Jusqu'à 10 $ ^ {14} ―― 1 $ peuvent être calculés correctement, mais à 10 $ ^ {15} ―― 1 $, comme prévu, le nombre est un plus grand que la bonne réponse.

Il y avait quelque chose qui m'est venu à l'esprit ici. "La précision des nombres à virgule flottante est d'environ 15 chiffres en décimal", a-t-il déclaré. Ruby Float est en fait dépendant de l'environnement, donc la précision ne peut pas être déclarée sans équivoque, mais c'est IEEE dans un grand nombre d'environnements. Il semble que 754 "double précision" soit utilisé. Dans ce cas, la précision est d'environ 15 chiffres en décimal.

Par conséquent, il est tout à fait possible que le résultat de Math.log10 (x) .floor + 1 avec un entier de 15 9s ne soit pas le nombre correct de chiffres.

Conclusion

Pour les petits entiers, Math.log10 (x) .floor + 1 convient, mais pour les grands entiers, il y a une erreur.

Recommended Posts

Le nombre de chiffres peut-il être Math.log10 (x) .floor + 1?
Comptez le nombre de chiffres après la virgule décimale en Java
Nombre de chiffres de l'élément de type numérique
Comment déterminer le nombre de parallèles
À propos du nombre de threads de Completable Future
[Java] Vérifiez le nombre d'occurrences de caractères
[Java] Faites attention au type de clé de la carte
J'ai vérifié le nombre de taxis avec Ruby