我的程序(6):分数小数互相转换

原创 2007年09月14日 18:01:00
# -*- coding: utf-8 -*-
#
author : wayne   http://blog.csdn.net/wayne92/
#
email:moonbingbing@gmail.com

import time

def decimal_to_fraction(value,radix):
    
'''
        把小数转换为分数。
        方法:比如输入0.21,radix为2.那么0.21=21/100,因为要求分母为
        2位,所以分母要变小,所以分子也要随着变小。分子的范围就是[1,21].
        根据每个分子的不同,int(分母)=分子/0.23, 再由分子/分母得出一个近似值。
        只要找出误差最小的那个就可以了。
        Args:
            value:小数的值。
            radix:分母的位数。
        Returns:
            返回tuple:(正负号,整数部分,分子,分母,
            (分子/分母)的值,(分子/分母)表示的循环小数,误差)
    
'''
    
#if str(value) == repr(value): 
    #    return None
    
    
if value < 0:    #把负数转换为正数
        sign = '-'
        value 
= abs(value)
    
else:
        sign 
= '+'
        
    base 
= 10**radix   
    integer 
= int(str(value).split('.')[0])   #整数部分
    value = value - integer                   #小数部分
    min_error = 1                             #最小误差
    best = None                               #返回tuple
    circulator = 0                            #得到分数的循环小数
    
    int_numerator 
= int(value*base)          #int_numerator为分子的最大值
    
    
    
for numerator in range(int_numerator,0,-1):
        result 
= numerator / value
        denominator 
= int(result+0.5)
        
if denominator == base:
            
continue
        
        my_value 
= float(numerator)/denominator
        error 
= abs(my_value - value)
        
        
if min_error > error:
            min_error 
= error
            circulator 
= fraction_to_circulator(numerator,denominator)
            best 
= (sign,integer,numerator,denominator,my_value,circulator,min_error)
            
if min_error == 0:  #找到第一个误差为0的值,就退出.如果不这样处理,效率会低很多。 
                break
          
    
return best

def fraction_to_circulator(dividend, divisor, precision=1000): 
    
'''
        把分数转换为循环小数。
        理论依据:任何分数都可以转换为有限小数或者无限循环小数。
        Args:
            dividend: 被除数
            divisor:  除数
            precision:精度。即计算循环小数时,最多计算到的小数点后多少位
        Returns:
            循环小数(字符串)。格式为:1.2(34)。括号中的是循环体。
    
'''
    pos 
= 0
    modDict 
= {}
    frac 
= []
    is_circulator 
= False       #是否存在循环
    
    div, mod
= divmod(dividend, divisor) 
    intPart 
= str(div) + '.' 
    
    
#模拟手算的过程,发现有相同的余数就说明发现循环
    while pos < precision and mod != 0 : 
        modDict[mod] 
= pos 
        mod 
*= 10 
        div, mod 
= divmod (mod, divisor) 
        frac.append(str(div)) 
        
if mod in modDict.keys():
            is_circulator 
= True
            
break 
        pos 
+= 1 
        
    
if is_circulator:                       # 发现循环 
        frac.insert(modDict[mod],'('
        frac.append(
')'
    
return intPart + ''.join(frac) 

  
def circulator_to_fraction(circulator):
    
'''
        把循环小数转换为分数。
        理论依据:每个循环小数都可以很精确的用一个分数来表示。
        方法:比如输入0.23(45).先记录循环体的位置,再转换为0.2345。
        0.2345... × 100   = 23.45...  (1)
        0.2345... × 10000 = 2345.45... (2) #这里100和10000是算出来的,不是乱写的
        用(2) - (1),得:
            0.2345... * 9900 = 2345 - 23 = 2322
        所以0.2345... 的分数表示就是 2322/9900.
        Args:
            circulator:循环小数(字符串)。格式为:1.2(34)。括号中的是循环体。
        Returns:
            如果格式输入有错误,显示提示,返回None。
            否则返回tuple(分子,分母)。
    
'''
    dot 
= circulator.find('.')
    left_p 
= circulator.find('(')
    rigth_p 
= circulator.find(')')

    
if dot == -1 or left_p == -1 or rigth_p == -1:
        
print u'输入循环小数格式错误'
        
print u'输入格式为 1.23(45),其中45为循环体'
        
return None
    
    true_circulator 
= float(circulator[:left_p] + circulator[left_p+1:-1])

    first_shift 
= left_p-dot-1
    second_shift 
= rigth_p-left_p-1+first_shift
    
    first_base 
= 10**first_shift
    second_base 
= 10**second_shift

    denominator 
= second_base - first_base  #分母
    numerator = int(true_circulator*second_base) 
                
- int(true_circulator*first_base)  #分子
                
    
return (numerator,denominator)

if __name__ == '__main__':
    
    begin 
= time.time()
    
    
print decimal_to_fraction(0.0629226211751451,2)
    
#print fraction_to_circulator(24,999) 
    #print circulator_to_fraction('0.78(0234)')
    
    end 
= time.time()
    
print 'cost time is %f'%(end - begin)
    
 
利用这种方法实现分数小数的互相转换,发现比ET要准确。ET下一个版本用我的算法吧,呵呵
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C小数转换分数的函数

hdu 1717 && 计蒜课 52 【分数小数的互相转化】【数论?】

本帖研究的是小数化分数与分数化小数 小数化分数 :http://acm.hdu.edu.cn/showproblem.php?pid=1717 分数化小数 : http://nanti.jisua...

十进制小数分数与二进制的转换

十进制小数分数与二进制的相互转换

小数转换分数

小数转换分数          小数转换成分数的时候,是让小数有更精确的表示。这个问题可以分两种情况来解决:有限小数和循环小数。     对于有限小数: 我们可以直接把后面...

分数转小数 代码

hdu 1717 小数化分数2(数学)

小数化分数2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S...

小数转分数

  • 2015-10-28 13:15
  • 14KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)