Finding a reasonably accurate fractional approximation to a number, even allowing a certain degree of suboptimality in the estimation, is not computationally efficient. So, computing with fractions almost immediately becomes computing with bigints, unless you get lucky and stuff cancels out.
If you start with the idea that you want to store every number in the same finite number of n bits, you’ve got a problem: you can store (at most) 2^n different numbers in n bits, but there are infinitely many numbers.
So, if you want to hold on to that idea, the question becomes what numbers best to pick.
If you go for rational numbers, you soon discover that addition of rationals is slow because you have to [1] multiply the denominators and find a greatest common divisor (example: 1/3 + 1/9 = (19 + 13)/(3*9) = 12/27 = 4/9)
You also will find that your denominators can rapidly get large, and that, in real life, you need to represent a fairly wide range of numbers (say at least between 10^-3 and 10^6). That means you either accept large, random rounding in calculations, or have to pick a large number of bits
Also, the math you have to do to find the closest rational for square roots and results of goniometric functions makes those functions slow.
So, you either have to give up the idea to store rationals, or the idea to store every number in the same finite number of n bits. IEEE chooses the former for performance reasons.
[1] assuming you want to have a single representation for each rational. You likely want, as you don’t want to waste space and because you want equality testing to be simple.
You can start there then wind up with floating point.
Say we have a 32 bit CPU. Let's store fractions in two halves, the numerator and denominator.
This turns out to be super inconvenient for irrational numbers. We can use an alternative representation where the number is in two halves, the integer half and fractional half. In other words your first 32 bits are 1X2^0...31 and second 32 bits are 1x2^-1...-32. This is called fixed point.
You run into a problem where this is usually extremely wasteful in the number of bits used, so you can fuse them into a single 32 bits used, and the binary decimal point is at the 16th bit, 18th bit, whatever you need. You just need to track it when multiplying or dividing numbers to handle the appropriate shifts. This is "fixed" point math, and it's what we did for decades because it's super cheap in hardware (it's the same integer adders/multipliers, just some extra work for division and shifting for multiplication).
You might even want the decimal point to move. Say your numbers are almost always less than 1, why use more than 1 bit for the integer part and in software, handle the overflows and change of decimal point when needed?
Well that software part is super complex, so you can implement some special hardware to do it. It's even really convenient to change the representation from a fixed integer and decimal half to a decimal mantissa and integer exponent. Now you've reinvented floating point. It would be great if there was a standard so all languages could agree on representation and hardware to implement it really fast. That's IEEE 754.
Common Lisp does by default. Calling (/ 1 3) gives 1/3 which is a rational. The individual components of a rational number are bignums, so the size of the fraction is only limited to available RAM.
However, this is not enough in many cases. For example, how would you store pi? In the case of Lisp, pi is stored as a floating point number, and the conversion rules say that a mathematical operation between a rational and a floating point number yields a floating point number. This means that even though you have rational numbers, you still have to be aware of floating point.
Of course, ultimately this is going to be a compromise and I understand the choice of not storing common constants that way. In the end you'd end up just replicating common mathematical notation and computing with that is not going to be fast.
The idea that it's somehow morally lacking to put less value on performance on machines are literally thousands of time faster than those used for early programming has always struck me as rather odd.
When I think of the problem what I see is the compiler pretends to be fast by forcing the programmer to deal with the problems. Bonus the solutions are inherently fragile and bug ridden. Which the programmer gets smugly blamed for.