[Python3] "A // B" et "math.floor (A / B)" ne sont pas toujours les mêmes! ??

Mise en garde

** Cet article contient l'histoire du "Atcoder Beginner Contest 148 E --Double Factorial". Veuillez vous abstenir de naviguer si vous prévoyez de résoudre ce problème vous-même. ** **

Aperçu

J'ai eu un problème de titre lors de la résolution d'Atcoder, donc je posterai cet article comme rappel et pour entendre les opinions des experts Python.

problème

Atcoder Beginner Contest 148 E - Double Factorial

Pour un entier n supérieur ou égal à 0, définissez f (n) comme suit:

· F(n) = 1 [n <Quand]\\
· F(n) = nf(n-2) [n \Lorsque geq 2]

Étant donné l'entier N. Trouvez combien de 0 suivent lorsque f (N) est écrit en décimal.

environnement

phénomène

Dans les deux codes suivants, ** la partie supérieure est AC (réponse correcte) **, mais la partie inférieure est WA (réponse incorrecte) **.

AC.py


import math
N = int(input())
ans = 0
if N % 2 != 0:
    pass
else:
    for i in range(0, 25):
        ans += N // (10 * 5 ** i)
print(ans)

WA.py


import math
N = int(input())
ans = 0
if N % 2 != 0:
    pass
else:
    for i in range(0, 25):
        ans += math.floor(N / (10 * 5 ** i))
print(ans)

Il existe 15 cas de test pour ce problème, mais les 2 cas de test suivants sont devenus WA.

[15.txt]
IN:  237590337949089028
OUT: 29698792243636116

[16.txt]
IN:  999003990299500294
OUT: 124875498787437525

Cause attendue

** La cause probable est une orthographe de ce que j'ai essayé de diverses manières jusqu'à ce que j'identifie la cause. ** ** ** Je veux juste connaître le résultat! J'espère que vous pourrez passer au chapitre suivant. ** **

Les parties suivantes concernent AC et WA.

ans += N // (10 * 5 ** i) #AC
ans += math.floor(N / (10 * 5 ** i)) #WA

Les deux font des choses similaires et sont susceptibles de donner le même résultat, mais pas.

Pour le moment, sortons où l'erreur se produit. Faites comme suit.

debug.py


import math
N = int(input())
ans_ac = 0
ans_wa = 0
if N % 2 != 0:
    pass
else:
    for i in range(0, 25):
        ans_ac = N // (10 * 5 ** i)
        ans_wa = math.floor(N / (10 * 5 ** i))
        print('i =', i)
        print('d =', N / (10 * 5 ** i))
        print('AC:', ans_ac)
        print('WA:', ans_wa)

Le résultat est le suivant.

i = 0 #Erreur: 2
d = 2.3759033794908904e+16
AC:  23759033794908902
WA:  23759033794908904

i = 1 #Erreur: 1
d = 4751806758981781.0
AC: 4751806758981780
WA: 4751806758981781

i = 2 #Erreur: 0
d = 950361351796356.1
AC: 950361351796356
WA: 950361351796356

i = 3 #Erreur: 0
d = 190072270359271.22
AC: 190072270359271
WA: 190072270359271

(Omis ci-dessous)

Les répétitions suivantes (i vaut 3 ou plus et moins de 25) avaient toutes 0 erreurs AC et WA (AC et WA sont égaux). Il semble qu'il n'y ait eu une erreur qu'au début de l'itération (i = 0, 1). Pour le moment, je ne semble rien savoir tel quel, alors j'ai décidé de penser à quelque chose de différent.

Il y avait une chose qui m'est venue à l'esprit ici. Quels sont les types de ces calculs? Il existe deux types en Python qui représentent des nombres réels.

Le premier n'a pas de limites de précision, mais le second en a. Quel type de décalage ont les deux méthodes de calcul en question?

abc.001.jpeg

Concernant «//», selon le Document officiel

x // y Le quotient de x et y est arrondi vers le bas Également connue sous le nom de division entière. Le type de résultat n'est pas nécessairement un type entier, mais la valeur de résultat est un entier. Le résultat est toujours arrondi vers l'infini négatif.

Il y a. Dans le calcul AC, il semble qu'elle soit affectée à une variable sans devenir une seule fois un type flottant.

Mais qu'en est-il des calculs WA? Cela passe par le type float une fois en fonction du résultat du calcul de «x / y». Je l'ai vérifié dans l'environnement à portée de main.

test.py


A = 4
B = 2
print(type(A), type(B))
print(type(A / B))
print(A / B)

'''
<class 'int'> <class 'int'>
<class 'float'>
2.0
'''

En d'autres termes, c'est déjà un type float avant d'utiliser math.floor (). «//» et «math.floor ()» ne sont-ils pas similaires et différents? J'ai pensé, mais cela ne semble pas être la cause.

La définition de «math.floor ()» dans Official Documents est la suivante.

Renvoie le "plancher" de x (le plus grand entier inférieur ou égal à x). Si x n'est pas un nombre à virgule flottante, x .__ floor __ () est exécuté en interne et une valeur intégrée est renvoyée.

Au contraire, je m'attendais à ce que le calcul WA soit via ** float type **, en passant une valeur inappropriée à math.floor () en premier lieu.

Comme mentionné au moment de l'introduction du type, le type float a une limitation de précision contrairement au type int. Il y avait les moyens suivants pour vérifier cela.

dig.py


import sys
print(sys.float_info.dig)
# 15

Le Document officiel est le suivant.

sys.float_info Taples nommés contenant des informations sur les types de flotteurs dig: Chiffre décimal maximum pouvant être affiché avec précision en virgule flottante

Apparemment, le type de flotteur peut être précis jusqu'à 15 chiffres, mais les chiffres au-delà sont suspects ... Maintenant, reconfirmons le cas de test qui a émis le WA plus tôt. Cette fois, nous allons nous concentrer sur le nombre de chiffres.

i = 0 #Erreur: 2
d = 2.3759033794908904e+16 #17 chiffres,Minorité 0 chiffres
AC:  23759033794908902     # 23759033794908904
WA:  23759033794908904     #17 chiffres>15 chiffres

i = 1 #Erreur: 1
d = 4751806758981781.0     #16 chiffres,Minorité 1 chiffre
AC: 4751806758981780       #16 chiffres>15 chiffres
WA: 4751806758981781

i = 2 #Erreur: 0
d = 950361351796356.1      #15 chiffres,Minorité 1 chiffre
AC: 950361351796356        #15 chiffres=15 chiffres
WA: 950361351796356

i = 3 #Erreur: 0
d = 190072270359271.22     #15 chiffres,2 chiffres
AC: 190072270359271        #15 chiffres=15 chiffres
WA: 190072270359271

(Omis ci-dessous)

La partie chiffre entier est cette fois importante pour la réponse au problème d'Atcoder. Il s'avère qu'une erreur se produit lorsque les chiffres entiers sont supérieurs à la précision de type float de 15 chiffres! Lorsque 4 <= i <25, le chiffre entier ne dépasse jamais 15 chiffres, il semble donc qu'il n'y ait pas eu d'erreur.

Il semblait que AC n'était pas cette fois en mordant le type float d avec l'erreur dans math.floor ().

Résumé

--ʻA // Betmath.floor (A / B) font la même chose --Lorsque ʻA et B sont de type entier (int) ʻA // B est sorti comme ** type entier ** --Même si ʻA et B sont de type entier (int), math.floor (A / B) est ʻA / B` via ** type float **.

C'est tout. Merci pour la lecture!

Recommended Posts

[Python3] "A // B" et "math.floor (A / B)" ne sont pas toujours les mêmes! ??
Python a + = b et a = a + b sont différents
Python open et io.open sont les mêmes
python memo- "sinon A et B" était "si (pas A) et B"
a () et a .__ call__ () ne sont pas équivalents
[Python] renvoie A [ou / et] B
ffmpeg-Construisez un environnement python et divisez la vidéo
Prise en compte des forces et faiblesses de Python
Python3> rond (a --b, 7)
Le VIF calculé par Python et le VIF calculé par Excel sont différents .. ??
Les nombres de type flottant ne sont pas les mêmes que la minorité de nombres décimaux
Une solution au problème que les fichiers contenant [et] ne sont pas répertoriés dans glob.glob ()
Le modèle linéaire généralisé (GLM) et le réseau neuronal sont les mêmes (1)
Assurez-vous que tous les éléments de la liste sont les mêmes en Python
Différent du type d'importation de python. Signification de depuis A import B
Créez le code qui renvoie "A et prétendant B" en python
Impossible d'utiliser les commandes python et pip sur CentOS (RHEL) 8
Le modèle linéaire généralisé (GLM) et le réseau neuronal sont les mêmes (2)
Le websocket de toio (nodejs) et python / websocket ne se connecte pas.
J'ai essayé de trouver la différence entre A + = B et A = A + B en Python, alors notez
Nouvelle grammaire et fonctionnalités Python non mentionnées dans le livre d'introduction
l'expression régulière de python, str et unicode sont sobres et addictives
Vérification de la théorie selon laquelle "Python et Swift sont assez similaires"
[Introduction à Python] Comment utiliser l'opérateur booléen (et ・ ou ・ non)
Comment afficher les octets de la même manière en Java et Python
L'histoire de Python et l'histoire de NaN
Explication ABC127 A, B, C (python)
[Python] Que sont @classmethod et les décorateurs?
[Python] Faire de la fonction une fonction lambda
ABC128 Commentaire A, B, C (python)
Explication ABC126 A, B, C (python)
[Introduction à Python] Quelle est la différence entre une liste et un taple?
[Explication AtCoder] Contrôle ABC184 Problèmes A, B, C avec Python!
Je pensais que c'était la même chose que python, et j'étais accro au problème que l'interpréteur ruby ne démarre pas.
Résoudre ABC175 A, B, C avec Python
Les modules et packages en Python sont des "espaces de noms"
Ecrire le test dans la docstring python
Rechercher le labyrinthe avec l'algorithme python A *
Connectez beaucoup de Python ou et et
python> Arguments de mot clé> hoge (** {'a': 1, 'b': 2, 'c': 3})
Exécuter l'interpréteur Python dans le script
[python] Générer une séquence qui considère les mêmes éléments
[python] [meta] Le type de python est-il un type?
Python> Python n'inclut pas le dernier décalage
Résoudre ABC165 A, B, D avec Python
Une histoire sur Python pop and append
Academia Potter et le mystérieux Python Pass
L'histoire du traitement A du blackjack (python)
[Python] Une barre de progression sur le terminal
[Python] Un programme qui arrondit le score
Créer en Python sans fichier image factice dans Django et tester le téléchargement de l'image
Transformez un programme Python en démon et exécutez-le automatiquement au démarrage du système d'exploitation
[Explication AtCoder] Contrôlez les problèmes A, B, (C), D de ABC165 avec Python!
[Explication AtCoder] Contrôlez les problèmes A, B, C, D d'ABC183 avec Python!
Python --Lisez les données d'un fichier de données numériques et recherchez la ligne de régression multiple.
Script Python qui lit les fichiers SQL, exécute BigQuery et enregistre le csv
Créons un système de réception simple avec le framework sans serveur Python Chalice et Twilio
Utilisez libsixel pour générer Sixel en Python et générer le graphe Matplotlib vers le terminal.