26

Interesting pattern came up as I go through the homework replies of my students. Why is there no RationalQ or RealQ? We have Rational and Real as type restrictors / heads in pattern matching, like _Rational or _Real. Why no Qs for them?

gwr
  • 13,452
  • 2
  • 47
  • 78
Andreas Lauschke
  • 4,009
  • 22
  • 20
  • 6
    It's a good question, really, since we do have IntegerQ. If you need something like that, you can always use a curried form like RationalQ = MatchQ[_Rational]. – Sjoerd Smit Sep 12 '18 at 13:36
  • 6
    No good answer to this one ... but people regularly make the mistake of assuming that IntegerQ tests if an expression is mathematically an integer (what it does is that it checks if the datatype is Integer) – Szabolcs Sep 12 '18 at 13:38
  • 1
    @SjoerdSmit Good idea, but I can "break" it: RationalQ[(1 - Sqrt[2]) (1 + Sqrt[2])]. ;) – Henrik Schumacher Sep 12 '18 at 13:39
  • 4
    @HenrikSchumacher: How does that break it? I wouldn't expect a function like RationalQ to perform algebraic simplifications: it should just check the data type. If you want to simplify, you should use Simplify. Mathematica already has enough annoying simplification behaviours that are difficult to stop. – Sjoerd Smit Sep 12 '18 at 13:44
  • @SjoerdSmit Good point. Even IntegerQ cannot simplify that. – Henrik Schumacher Sep 12 '18 at 13:48
  • 6
    For the math (not datatype), one would use Element[x, Rationals] instead. That will often not evaluate, but it is Simplifyable. It doesn't check datatype. It's checks whether the value is rational. – Szabolcs Sep 12 '18 at 13:57
  • 4
    If there were a RationalQ, I'd expect RationalQ[2] to be False because the datatype of 2 is Integer, not Rational. That has nothing to do with 2 being a rational number. – Szabolcs Sep 12 '18 at 13:58
  • 4
    Related question on RealQ – Rohit Namjoshi Sep 12 '18 at 14:41
  • 1
    _Rational is not sufficient as Rational[x,y] with (x,y symbols) is not an atomic Rational. There should be a RationalQ. – Szabolcs Apr 17 '19 at 22:09

2 Answers2

23

There is a RealQ, see

Developer`RealQ

Also relevant:

Developer`MachineRealQ

The difference between the two:

Developer`RealQ[1.`20]
Developer`MachineRealQ[1.`20]

True

False

So, Developer`RealQ is a test for arbitrary precision numbers, while Developer`MachineRealQ checks whether its input is a double precision number.

Notice that both return

Developer`RealQ[1]
Developer`MachineRealQ[1]

False

False

Compare this to

IntegerQ[10^100000]
Developer`MachineIntegerQ[10^100000]

True

False

As Szabolcs and Sjoerd pointed out, these tests are for data types and not tests in mathematical sense. For example, we also have the following:

IntegerQ[(1 - Sqrt[2]) (1 + Sqrt[2])]
IntegerQ[Simplify[(1 - Sqrt[2]) (1 + Sqrt[2])]]

False

True

A somewhat more mathematical test seems to be Assumptions`ARealQ:

Assumptions`ARealQ[(1 - Sqrt[2]) (1 + Sqrt[2])]

True

But as it is undocumented, I really don't know what does it do.

And on top of that, we have Assumptions`ARationalQ, quite a mysterious beast:

Assumptions`ARationalQ[(1 - Sqrt[2]) (1 + Sqrt[2])]
Assumptions`ARationalQ[1/2]
Assumptions`ARationalQ[1]
Assumptions`ARationalQ[I]
Assumptions`ARationalQ[1.]

False

True

True

False

False

Not to mention Reduce`RationalNumberQ which behaves similarly erratic.

Jason B.
  • 68,381
  • 3
  • 139
  • 286
Henrik Schumacher
  • 106,770
  • 7
  • 179
  • 309
  • (1 - 3 I) + (I ArcSinh[7])/ArcSinh[1] is a real number, but Developer`RealQ and MachineRealQ returns False. – expression Jan 22 '21 at 13:22
  • Of course it is not a machine real, because it is an exact number. Only Re[N[(1 - 3 I) + (I ArcSinh[7])/ArcSinh[1]]] would turn it into a machine real. E.g., also Developer`MachineRealQ[1] would return False. I think that Developer`MachineRealQ works as it should. I don't now however, why Developer`RealQ does not classify it as a real number. Both functions are undocument and thus so not meant for the public. We just cannot tell what the designers intendended and whether they work correctly in that regard. – Henrik Schumacher Jan 22 '21 at 13:54
17

Why no RationalQ or RealQ?

Probably because it isn't unambiguous what such a function should do. From the comments above:

If there were a RationalQ, I'd expect RationalQ[2] to be False

But many other users would expect something like this:

enter image description here

For IntegerQ there aren't such conflicting expectations.

Jason B.
  • 68,381
  • 3
  • 139
  • 286