中学社会668760 views
高校物理160203 views
教育149510 views
小学算数1200427 views
Computer368106 views
英語613639 views
小学社会310485 views
世界の国564520 views
高校化学2924392 views
高校国語788336 views
Help
Tools
NewsSpreadsheetCalendarBookkeepingSlidesTier ListPen ToolIllustrationCrayonWatercolorPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchSwirl EffectLine ArtOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsRolling DiceCross SectionsMotion PathMechanicsWavesElectromagnetic WavesCapacitorsLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHOrganic Reaction MapPeriodic TableComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseMuscle ContractionHormones and HomeostasisRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic TheoryShogi StrategyPiano Rhythm Game

English

分数で正確に計算する(fractions.Fraction)|Python

浮動小数点数では 1/3 を正確に表現できない。0.333... と無限に続く小数を有限のビットで表すため、どうしても誤差が生じる。分数のまま計算したい場面では fractions.Fraction を使う。

Fraction の基本

Fraction は分子と分母を整数で保持し、演算結果も分数のまま返す。

from fractions import Fraction

a = Fraction(1, 3)
b = Fraction(1, 6)

print(a + b)  # 1/2
print(a * b)  # 1/18
print(a / b)  # 2

1/3 + 1/6 は通分して 2/6 + 1/6 = 3/6 = 1/2 となる。Fraction は自動的に約分してくれるため、結果は常に既約分数で得られる。

浮動小数点数との違い

浮動小数点数で同じ計算をすると、微小な誤差が紛れ込む。

# 浮動小数点数
x = 1/3 + 1/6
print(x)  # 0.5
print(x == 0.5)  # True(この例ではたまたま一致)

# しかし別の例では
y = 0.1 + 0.1 + 0.1
print(y)  # 0.30000000000000004
print(y == 0.3)  # False

一方、Fraction なら誤差は生じない。

from fractions import Fraction

y = Fraction(1, 10) + Fraction(1, 10) + Fraction(1, 10)
print(y)  # 3/10
print(y == Fraction(3, 10))  # True

様々な初期化方法

Fraction は複数の方法でインスタンス化できる。

from fractions import Fraction

# 分子と分母を指定
Fraction(3, 4)  # 3/4

# 整数から
Fraction(5)  # 5

# 文字列から
Fraction('3/4')  # 3/4
Fraction('0.75')  # 3/4
Fraction('-1.25')  # -5/4

# 浮動小数点数から(注意が必要)
Fraction(0.5)  # 1/2
Fraction(0.1)  # 3602879701896397/36028797018963968(誤差を含む)

浮動小数点数から Fraction を作ると、元の浮動小数点数が持っていた誤差がそのまま分数に変換される。0.1 は内部的に 0.1 ちょうどではないため、奇妙な分数になる。文字列 '0.1' から作れば Fraction(1, 10) が得られる。

limit_denominator で近似

巨大な分母を持つ分数を、指定した分母以下の近似分数に変換できる。

from fractions import Fraction
import math

# 円周率を分数で近似
pi_frac = Fraction(math.pi)
print(pi_frac)  # 884279719003555/281474976710656

# 分母を 1000 以下に制限
approx = pi_frac.limit_denominator(1000)
print(approx)  # 355/113
print(float(approx))  # 3.1415929203539825

355/113 は「密率」と呼ばれる円周率の近似分数で、中国の数学者・祖沖之が 5 世紀に発見した。分母が小さい割に驚くほど精度が高い。

分子と分母の取得

numeratordenominator 属性で分子・分母を取り出せる。

from fractions import Fraction

f = Fraction(7, 12)
print(f.numerator)  # 7
print(f.denominator)  # 12

使いどころ

Fraction は金融計算や数学的な厳密性が求められる場面で有用だ。ただし、計算速度は浮動小数点数より遅く、分子・分母が大きくなるとメモリ消費も増える。パフォーマンスが重要な場面では decimal.Decimal や通常の float を検討する。

Fraction

分数のまま正確に計算できる。約分も自動。ただし速度は遅め。

float

高速だが、10 進数を正確に表現できない場合がある。科学計算向き。

有理数の範囲で正確な計算が必要なら Fraction を選ぶとよい。