最近想要做到一个数学计算的项目,其中需要把float或double转换为分数(a/b)的表达形式,但苦于网上没有合适的教程,于是自己研究了float和double的数据类型,结果成功,决定和大家分享代码。


实现基本分数结构

分数的英文是Fraction,因此我们可以写一个Fraction类来存储一个分数,一个long存储分子,一个long存储分母,基本的结构看上去是这样的:

public class Fraction {public long a,b; // 不要吐槽,懒得起其他名字了// 不过要注意的一点是我很反感大量无用的Getter/Setter// 不仅使代码冗杂,而且拉低程序运行速度public Fraction(long a, long b) {this.a=a; this.b=b;if (b == 0)throw new RuntimeException("分母不能为0");Appointment();}private static long gcd(long a, long b) { // 用辗转相除法求最大公约数return b==0? a: gcd(b,a%b);}public void Appointment() { // 约分操作,来自百度翻译if (a == 0 || b == 1) return; // 如果分子是0或分母是1就不用约分了long gcd = gcd(a,b);this.a /= gcd;this.b /= gcd;}public float toFloat() {return (float) a/b;}public double toDouble() {return (double) a/b;}@Overridepublic String toString() {if (b == 1) return Long.toString(a); // 如果分母是1,直接返回分子的数字形式return Long.toString(a) + '/' + Long.toString(b);}
}

完成!上面的代码用到了辗转相除法获取分子与分母之间的最大公约数,感兴趣的朋友可以去百度上找找
相信上面的代码是很易懂的,那么我们就可以开始测试了!

测试代码:

Fraction a = new Fraction(2,4);
System.out.println(a); // 输出 '1/2'
System.out.println(a.toDouble()); // 输出 '0.5'

好,那让我们开始下一步!

实现分数相互运算

分数的运算我就不再赘述了,这里就简单地列举一下吧:

  • 加法: ab+cd=ad+bcbd a b + c d = a d + b c b d \frac{a}{b}+\frac{c}{d}=\frac{ad+bc}{bd}
  • 减法: ab−cd=ad−bcbd a b − c d = a d − b c b d \frac{a}{b}-\frac{c}{d}=\frac{ad-bc}{bd}
  • 乘法: ab×cd=acbd a b × c d = a c b d \frac{a}{b}\times\frac{c}{d}=\frac{ac}{bd}
  • 除法: ab÷cd=adbc a b ÷ c d = a d b c \frac{a}{b}\div\frac{c}{d}=\frac{ad}{bc}

好的,接下来就是我们具体的实现了

public Fraction Plus(Fraction b) {return new Fraction(this.a*b.b + this.b*b.a, this.b*b.b);
}
public Fraction Minus(Fraction b) {return new Fraction(this.a*b.b - this.b*b.a, this.b*b.b);
}
public Fraction Multiply(Fraction b) {return new Fraction(this.a*b.a, this.b*b.b);
}
public Fraction Divide(Fraction b) {return new Fraction(this.a*b.b, this.b*b.a);
}

完美!现在我们已经基本完成了我们的分数类了
现在我们要实现本篇文章要讲的一个重要功能——

将float和double转换为分数

在实现这一功能之前,我们需要了解一下float和double的存储方式
float存储方式
double存储方式
简单地来说,float和double都是由三个部分组成的:符号位 S ,指数 E 和底数 M
其中,符号位只占一位,指数在float中占8位,double中占11位;底数在float占23位,double中占52位。
于是研究了Float.toString和Double.toString的代码之后,代码就显而易见了 - Show Me the Code!

public static Fraction valueOf(double q) {long i = Double.doubleToRawLongBits(q);boolean negative = (i & -9223372036854775808L) != 0L;long M = i & 4503599627370495L; // 获取实际数字位 Mint E = (int) ((i & 9218868437227405312L) >> 52); // 获取指数位 Eif (E == 2047) { // 特殊数字if (M == 0) // Infinityreturn null;else // 不是一个合法的doublereturn null;} else {if (E == 0) {if (M == 0)return new Fraction(0, 1);int back = Long.numberOfLeadingZeros(M) - 11;M <<= back;E = 1 - back;} elseM |= 4503599627370496L;E -= 1023;long b = 1;for (int w = E; w < 52; w++)b <<= 1;if (negative) M = -M;return new Fraction(M, b);}
}
public static Fraction valueOf(float q) {int i = Float.floatToRawIntBits(q);boolean negative = (i & -2147483648) != 0; // 是否为负数int M = i & 8388607; // 获取实际数字位 Mint E = (i & 2139095040) >> 23; // 获取指数位 Eif (E == 255) { // 特殊数字if ((long) M == 0L) // Infinityreturn null;else // 非法的floatreturn null;} else {if (E == 0) {if (M == 0)return new Fraction(0, 1);int back = Integer.numberOfLeadingZeros(M) - 8; // 获取顶部共有几个连续的0,-8即减去小数位M <<= back;E = 1 - back;} elseM |= 8388608; // 自动在顶位或上1,也就是第9位|=1E -= 127;int b = 1;for (int w = E; w < 23; w++)b <<= 1;if (negative) M = -M;return new Fraction(M, b);}
}

代码注释已经很详细了,大家就自己去探索吧。
这里顺便附上一个很有用的函数,可以打印出数字的二进制形态

private static void printBinary(int q) {int S = 32;boolean[] d = new boolean[S];for (int i = S - 1; i >= 0; i--) {d[i] = (q & 1) == 1;q >>= 1;}for (int i = 0; i < S; i++)System.out.print(d[i] ? '1' : '0');System.out.println();
}
private static void printBinary(long q) {int S = 64;boolean[] d = new boolean[S];for (int i = S - 1; i >= 0; i--) {d[i] = (q & 1) == 1;q >>= 1;}for (int i = 0; i < S; i++)System.out.print(d[i] ? '1' : '0');System.out.println();
}

Java 分数的实现 | 将float或double转换为分数相关推荐

  1. java中将int转换float_在java中将float和double转换为int时有什么区别?

    我用这些语句来测试 float f=4.35f; int i=(int)(f*100); System.out.println(i); double d=4.35; i=(int)(d*100); S ...

  2. Java String转int、float、double

    int i; String s1="134"; i=Integer.parseInt(s1); 如果是float可以用强制类型转换. Float.parseFloat(); Dou ...

  3. Java的不同进制输出,[DanoR][Java小码][进制转换::将double转换为不同进制后用String输出]...

    功能简述 进制转换 输入: 一个数(double),目标进制(int)和小数的保留位数(int) 输出: 相应进制的表示方式(String) 参数说明 double number; //将要被转换的数 ...

  4. 深入理解C++浮点数(float、double)类型数据比较、相等判断

    深入理解C++浮点数(float.double)类型数据比较.相等判断 浮点数在内存中的存储机制和整型数不同,其有舍入误差,在计算机中用近似表示任意某个实数.具体的说,这个实数由一个整数或定点数(即尾 ...

  5. Java中的简单浮点数类型float和double不能够进行精确运算

    在java中,简单的浮点类型float和double是不能够进行运算.我们先看下面的两个程序代码: 代码一: import java.util.Scanner; class Circle { doub ...

  6. float 与 double、隐式类型转换、switch、重写与重载、Java 与 C++ 的区别、JRE or JDK

    1.float 与 double 1.1 字面量属于 double 类型,不能直接将 1.1 直接赋值给 float 变量,因为这是向下转型. // float f = 1.1; Java 不能隐式执 ...

  7. Java中float和double精度

    http://zhidao.baidu.com/question/344295417.html?seed=0 float与double的区别 单精度浮点数在机内占4个字节,用32位二进制描述. 双精度 ...

  8. java的int、char、long、float、double对byte的转换,在通信的时候会用到

    /** * java的int.char.long.float.double对byte的转换,在通信的时候会用到 * <ul> * <li>文件名称: com.born.util ...

  9. java中float%int_java中short、int、long、float、double取值范围

    一.分析基本数据类型的特点,最大值和最小值. 1. 基本类型:int 二进制位数:32 包装类:java.lang.Integer 最小值:Integer.MIN_VALUE= -2147483648 ...

最新文章

  1. 机器人建图、感知和交互的语义研究综述
  2. 网站快照更新不及时有什么好的解决办法吗?
  3. 关于android系统集成其他传感器
  4. 计算机的智能化研究领域的是,科学网—第五代计算机为何在“智能化”阶段的发展像蜗牛般的徘徊前行? - 邹晓辉的博文...
  5. oracle 中查找不连续的数的最前一个值
  6. 扫地机器人单扫和双扫_618买扫地机器人前必看 别图便宜 小心入坑!
  7. 电大计算机专业毕业自我鉴定,电大毕业生计算机专业自我鉴定
  8. 用gdb来学习c语言(linux环境下)
  9. FastCGI 使用介绍
  10. Apache Spark Meetup China 第1期 最全资料下载
  11. select默认选中
  12. 全国银行开户行名称查询数据库,包括行号、电话、地址、
  13. 结绳计数——最原始的备忘录
  14. ListView制作简单表格
  15. 构建MFS+Keepalived双机高可用热备方案`
  16. 南京大学计算机课程表,南大课表新鲜出炉,哪个专业课程最多?
  17. Magento 过滤导航插件Mana
  18. 企业为什么要建网站?
  19. 遗传算法之优化BP神经网络
  20. 曾经年少不努力,不懂资本的魔力---《资本论》

热门文章

  1. 闪电邮验证服务器错误,网易、闪电邮如何错误查询
  2. WEB前端学习 (7)CSS复习六(布局-定位)
  3. ABOV单片机内部定时器Timer1的定时器代码实现讲解及示例代码-[MC96F6332D]
  4. 山海演武传·黄道·第一卷 雏龙惊蛰 第六章 八卦与奇门
  5. photoshop制作html,用Photoshop制作好的网页模板再来用dreamweave制作出html的简单教程...
  6. python语句的输出结果_Python 3.x 语句 print(1, 2, 3, sep=':') 的输出结果为 _____
  7. 西北工业大学计算机学院奖学金政策,西北工业大学本科生普通奖学金管理办法...
  8. InfluxDB SpringBoot Docker Grafana实战监控数据统计
  9. dt100g3什么意思_对金士顿DT100G364GBU盘简单测评
  10. 科技是一把双刃剑-医学技术