首页 > 其他分享 >一种不会丢失精度的分数表示法

一种不会丢失精度的分数表示法

时间:2023-02-19 21:34:31浏览次数:30  
标签:分数 down LD int up long 表示法 丢失 stand

我们都知道,C++中就算是精度最高的浮点数long double也会存在精度丢失的问题,那么我们该如何解决这个问题呢?高精度浮点数又显得过于夸张繁琐
![](/i/ll/?i=3f5d47f6e2ba4a48a9ce410be39bd218.png =300x300)
于是,我们想到了一种办法,用long long分别表示分母和分子
而我们在进行分数运算的时候,就可以模拟人工手算分数的办法来操作,比如说

\[\frac{a}{b}+\frac{c}{d}=\frac{ad+bc}{bd} \]

之后再求gcd约分即可
而比较两个分数的方法也很简单

\[\frac{a}{b}<\frac{c}{d}\ \Leftrightarrow\ ad<bc\ (a,b,c,d>0) \]

你以为这就完了吗?


不!

坑点:

  • 有负数时,比较大小时要分类讨论!
  • 约分时gcd不要传负数进去,概率出玄学错误!
  • 输出时分母的负号一定要传给分子,不然 -114514/1919810 就会输出成 114514/-1919810 !
  • 分母为1或者分子为0时,就不用输出分数线了!(这项看情况,有些题目强制分数形式输出)

上代码!

#include<bits/stdc++.h>
using namespace std;
using LL = long long;
struct Fraction{
    LL up/*分子*/,down/*分母*/;
    inline void reduction(){//约分
        if(up<0&&(down<0 || down<0)){//负号可以约掉 或 需要把分母符号移到分子
            up=-up;
            down=-down;
        }
        LL div=__gcd(abs(up),abs(down));//gcd最好加个绝对值不然可能爆玄学错误
        up/=div;
        down/=div;
    }
    inline void output(){//输出
        reduction();//再次约分确保安全
        cout<<up<<'/'<<down;
    }
    inline void reverse(){//取倒数
        swap(up,down);
    }
    Fraction operator + (const Fraction &x){
        Fraction res;
        res.up=up*x.down+down*x.up;
        res.down=down*x.down;
        res.reduction();
        return res;
    }
    Fraction operator - (const Fraction &x){
        Fraction res;
        res.up=up*x.down-down*x.up;
        res.down=down*x.down;
        res.reduction();
        return res;
    }
    Fraction operator * (const Fraction &x){
        Fraction res;
        res.up=up*x.up;
        res.down=down*x.down;
        res.reduction();
        return res;
    }
    Fraction operator / (const Fraction &x){
        Fraction res;
        res.up=up*x.down;
        res.down=down*x.up;
        res.reduction();
        return res;
    }
    inline bool operator < (const Fraction &x){
        int tmp=(down<0)+(x.down<0);//判断负数个数的简单写法,总不可能4种情况if一遍吧
        return tmp%2==0 ? (up*x.down<down*x.up) : (up*x.down>down*x.up);//极致压行,负数为奇数个变号,反之不变
    }
    inline bool operator <= (const Fraction &x){
        int tmp=(down<0)+(x.down<0);
        return tmp%2==0 ? (up*x.down<=down*x.up) : (up*x.down>=down*x.up);
    }
    inline bool operator > (const Fraction &x){
        int tmp=(down<0)+(x.down<0);
        return tmp%2==0 ? (up*x.down>down*x.up) : (up*x.down<down*x.up);
    }
    inline bool operator >= (const Fraction &x){
        int tmp=(down<0)+(x.down<0);
        return tmp%2==0 ? (up*x.down>=down*x.up) : (up*x.down<=down*x.up);
    }
    inline bool operator == (const Fraction &x){
        return up*x.down==down*x.up;
    }
    inline bool operator != (const Fraction &x){
        return up*x.down!=down*x.up;
    }
};
int main(){
    ios::sync_with_stdio(false);
    
    return 0;
}
/*
#include<bits/stdc++.h>
#define LD long double
using namespace std;
const int MAXN=2e5+5;
const LD eps=(LD)1.0e-30;
typedef pair<int,int> pii;
int n;
pii stand,inp[MAXN],ans;
LD mindelta=LDBL_MAX,mink,k,delta,stdk;
inline LD lfabs(LD x){
    if(x>=0) return x;
    else return -x;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    cin>>stand.first>>stand.second;
    stdk=(LD)stand.first/(LD)stand.second;
    for(int i=1;i<=n;i++){
        cin>>inp[i].first>>inp[i].second;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            k=((LD)abs(inp[i].second-inp[j].second))/((LD)abs(inp[i].first-inp[j].first));
            delta=lfabs(k-stdk);
            if(delta<mindelta || (lfabs(delta-mindelta)<=eps && k<mink)){
                mink=k;
                mindelta=delta;
                ans={abs(inp[i].second-inp[j].second),abs(inp[i].first-inp[j].first)};
            }
        }
    }
    int gcd=__gcd(ans.first,ans.second);
    cout<<ans.first/gcd<<'/'<<ans.second/gcd<<endl;
    return 0;
}
*/

标签:分数,down,LD,int,up,long,表示法,丢失,stand
From: https://www.cnblogs.com/SkyNet-PKN/p/17135648.html

相关文章

  • msvcp110.dll丢失怎么办 msvcp110.dll丢失解决方法
    计算机丢失msvcp110.dll是什么意思?如何修复?系统文件msvcp100.dll是存放在Windows系统中的重要文件,丢失很多软件跟游戏都无法打开,dll文件属于动态联结库,是微软公司在微软视窗......
  • rabbitmq消息丢失
    发送消息后,队列中没有显示最后发现只能在flatMap中创建和关闭RpcClient。publicMono<ServerResponse>addCart(ServerRequestrequest){AtomicReference<Cart......
  • 【服务器数据恢复】服务器迁移数据时数据丢失的数据恢复案例
    服务器数据恢复环境&故障:一台某品牌的存储设备,Windows操作系统。由于业务需求,需要把这台存储设备中的数据迁移到另外一台存储设备中,在迁移数据过程中突然无法读取数据,管理......
  • vue项目,使用query传参,页面显示重新刷新或回归后数据丢失
    1、将需要传输的数据使用  JSON.stringify()  转译成字符串形式进行传输  2、在需要接收的页面使用  JSON.parse()  将数据格式再转回来即可使用,且刷新回......
  • SpringBoot文件上传丢失Bug记录
    SpringBoot文件上传丢失Bug记录报错如下:java.io.FileNotFoundException:C:\Users\zbz12\AppData\Local\Temp\tomcat.708075972435741143.8080\work\Tomcat\localhost\c......
  • vcruntime140_1.dll丢失怎么安装?
    许多用户在使用电脑的时候,在安装运行某些程序的时候,电脑突然提示由于找不到vcruntime140_1.dll,无法继续执行代码,遇到这种情况我们应该怎么解决呢?下面小编就带着大家一起看看......
  • vuex页面刷新数据丢失
    一:数据丢失的原因vuex存储的数据只是在页面中,相当于全局变量,页面刷新的时候vuex里的数据会重新初始化,导致数据丢失。因为vuex里的数据是保存在运行内存中的,当页面刷新时......
  • RabbitMQ重启后数据和用户丢失
    1、问题描述:在重启RabbitMQ服务后,数据丢失,用户丢失。2、问题原因:在RabbitMQ服务启动后,对主机名进行过修改,而修改主机名会导致数据存储路径发生变化,如果不重启RabbitMQ不会......
  • 【服务器数据恢复】虚拟机文件丢失导致Hyper-V服务瘫痪的数据恢复案例
    服务器数据恢复环境:WinServer操作系统服务器,部署Hyper-V虚拟机环境;虚拟机的硬盘文件和配置文件存储在一台存储设备中;该存储设备配置:一组4盘raid5阵列存放虚拟机数据+单块......
  • 记一次虚机强制断电 K8s 集群 etcd pod 挂掉快照丢失(没有备份)问题处理
    写在前面不小心拔错电源了,虚机强制关机,开机后集群死掉了记录下解决方案断电导致etcd快照数据丢失,没有备份.基本上是没办法处理可以找专业的DBA来处理数据看有没有可......