Andy Allinger
Попробуйте все возможные знаменатели DENDIG
цифры или меньше.
Вычислите числитель как NUMER = NINT(X DENOM)
Держите самое близкое приближение.
Босс старой школы должен одобрить решение без мозгов в ФОРТРАН.
!-----------------------------------------------------------------------
! Convert a float to a fraction, by exhaustive search!
!-----------------------------------------------------------------------
FUNCTION F2F (INPVAL, DENDIG)
IMPLICIT NONE
REAL INPVAL ! float number
INTEGER DENDIG ! max digits in denominator
CHARACTER*32 F2F
INTEGER KTRIM, LTRIM ! external functions
INTEGER NUMER, DENOM, BESTN, BESTD, MAXDEN, K, L, WHOLE
REAL AERR, BESTER, FRACT
CHARACTER*32 NUMSTR
! begin
MAXDEN = 10 **DENDIG - 1
WHOLE = INT(INPVAL)
FRACT = INPVAL - FLOAT(WHOLE)
BESTER = 1.0
BESTD = 1 ! needless initializations
BESTN = 0 ! " "
DO 10 DENOM = MAXDEN, 2, -1 ! backwards step for extra confusion
NUMER = NINT(FRACT * FLOAT(DENOM))
AERR = ABS(FRACT - FLOAT(NUMER) / FLOAT(DENOM))
IF (AERR .LE. BESTER) THEN
BESTER = AERR
BESTN = NUMER
BESTD = DENOM
END IF
10 CONTINUE
! format output
F2F = ''
20 FORMAT (I16)
IF (WHOLE > 0) THEN
WRITE (UNIT=NUMSTR, FMT=20) WHOLE
K = KTRIM(NUMSTR)
L = LTRIM(NUMSTR)
F2F = NUMSTR(K:L)
END IF
WRITE (UNIT=NUMSTR, FMT=20) BESTN
K = KTRIM(NUMSTR)
L = LTRIM(NUMSTR)
F2F = F2F(1:LTRIM(F2F)) // ' ' // NUMSTR(K:L)
WRITE (UNIT=NUMSTR, FMT=20) BESTD
K = KTRIM(NUMSTR)
L = LTRIM(NUMSTR)
F2F = F2F(1:LTRIM(F2F)) // '/' // NUMSTR(K:L)
RETURN
END ! of F2F
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! substitute for LEN_TRIM for old compilers
FUNCTION LTRIM (STRING)
IMPLICIT NONE
CHARACTER*(*) STRING
INTEGER LTRIM
INTEGER J, L
L = LEN(STRING)
DO 50 J = L, 1, -1
IF (STRING(J:J) .EQ. ' ') GO TO 50
LTRIM = J
RETURN
50 CONTINUE
LTRIM = 0
RETURN
END ! of LTRIM
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! first non-blank position in character variable
FUNCTION KTRIM (STRING)
IMPLICIT NONE
CHARACTER*(*) STRING
INTEGER KTRIM
INTEGER J, L
L = LEN(STRING)
DO 50 J = 1, L, +1
IF (STRING(J:J) .EQ. ' ') GO TO 50
KTRIM = J
RETURN
50 CONTINUE
KTRIM = 0
RETURN
END ! of KTRIM
PROGRAM FPI ! test pi fractions
IMPLICIT NONE
INTEGER J
REAL PI
CHARACTER*32 F2F, STRING
PI = ACOS(-1.)
DO J = 1, 7
STRING = F2F(PI, J)
PRINT *, 'with ', J, ' digits, the best representation ',
$ 'of pi is ', STRING
END DO
STRING = F2F(.00205501, 6)
PRINT *, 'F2F(.00205501, 6): ', STRING
END ! of test program
пример вывода:
with 1 digits, the best representation of pi is 3 1/7
with 2 digits, the best representation of pi is 3 14/99
with 3 digits, the best representation of pi is 3 16/113
with 4 digits, the best representation of pi is 3 16/113
with 5 digits, the best representation of pi is 3 13966/98635
with 6 digits, the best representation of pi is 3 132749/937541
with 7 digits, the best representation of pi is 3 593883/4194304
F2F(.00205501, 6): 1293/629194 ! closer approximation !
Andy Allinger
Мое извинение. Изменена программа на двойную точность для 64-битной математики. Оказывается, ваш ответ для .00205501 был лучше, и что приближения Пи тоже были неправильными.
с 1 цифрой приблизительное число Пи равно 3 1/7
с 2 цифрами, приблизительно Пи составляет 3 14/99
с 3 цифрами приблизительное число Пи равно 3 16/113
с 4 цифрами приблизительное число Пи равно 3 16/113
с 5 цифрами приблизительное число pi равно 3 14093/99532
с 6 цифрами приблизительное число pi равно 3 140914/995207
с 7 цифрами приблизительное число Пи равно 3 244252/1725033
DF2F (. 00205501D0, 6): 1829/890020
Почему я вообще сомневался в математиках?