# Default Real (Float) kind?

**URL:** <https://discourse.julialang.org/t/default-real-float-kind/129631>\
**Category:** Internals & Design\
**Tags:** float\
**Created:** [June 4, 2025, 7:59am UTC](https://discourse.julialang.org/t/default-real-float-kind/129631 "2025-06-04T07:59:20Z")\
**Posts on this page:** 11\
**Page:** 3

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [June 6, 2025, 2:41pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/41 "2025-06-06T14:41:03Z")

</div>

> [@Tamas\_Papp](#):
>
> Eg we could create an object
> 
> ```julia
> struct DIC{T,S} # Deferred Irrational Computation
> op::T
> args:S
> end
> 
> ```
> 
> and arrange methods so that

A principled approach to this, which has the desired capabilities but is also clearly bounded and not just an ad hoc, incomplete CAS, is Hans Boehm’s real number API: [https://dl.acm.org/doi/10.1145/3385412.3386037](https://dl.acm.org/doi/10.1145/3385412.3386037). It was developed to spare Android users from floating-point nonsense when using the calculator app. There’s (of course) a [Rust implementation](https://github.com/tialaramex/realistic) whose readme has a concise description of the concept:

> The Real type in this crate represents a number which is a composite of a rational (a ratio between two potentially large integers) and some real value which we may not be able to compute exactly and so must be approximated for display, but which sometimes has a precise description we can track to take advantage of in further calculations.

Implementing this in Julia would be a fun side project for anyone with time to spare! Even cooler would be if it could somehow be made to handle all literal expressions in a module without requiring special syntax or operators.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [June 6, 2025, 2:46pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/42 "2025-06-06T14:46:51Z")

</div>

Here’s a twitter thread explaining the concept surprisingly well even if it’s written in an intensely annoying style: [https://xcancel.com/ChadNauseam/status/1890889465322786878](https://xcancel.com/ChadNauseam/status/1890889465322786878)

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [June 6, 2025, 2:50pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/43 "2025-06-06T14:50:29Z")

</div>

Same twitter thread content but in a normal web page (from the author): [calculator-app - Chad Nauseam Home](https://chadnauseam.com/coding/random/calculator-app) (~30% less annoying IMO 😁)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 6, 2025, 3:38pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/44 "2025-06-06T15:38:17Z")

</div>

> [@danielwe](#):
>
> A principled approach to this, which has the desired capabilities but is also clearly bounded and not just an ad hoc, incomplete CAS, is Hans Boehm’s real number API

While this is a very cool approach and I am itching to read through the paper, I would actually _prefer_ the “inexact” version. That is to say, once the precision is determined from the context, the computation should proceed _as if_ constants were to be numbers of that precision.

Eg I would want

```julia
exp(-1im * π) * BigFloat(2.7)

```

to be equal to

```julia
exp(-1im * BigFloat(π)) * BigFloat(2.7)

```

(which is complex with a small imaginary part, because of numerical error) and not

```julia
-BigFloat(2.7)

```

which a CAS would simplify to.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [June 6, 2025, 3:54pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/45 "2025-06-06T15:54:20Z")

</div>

In the real API, unless the system defines `exp(-1im * π)` as an exact symbolic constant, the RRA evaluation would at least give you `-BigFloat(2.7) + im * BigFloat(0.0)`, because it can’t prove that the imaginary part is exactly zero; it can only evaluate the imaginary part and find that it is zero the requested precision. Still not identical to what float arithmetic gives, though.

It would be natural to provide different modes, from just a little magic to a lot of magic, that vary in how many function-of-rational-times-irrational expressions are considered exact symbolic constants vs. represented using RRA. But the premise is that when converting the final expression to a finite-precision number, the result is exact to the requested precision, so you would indeed get different results from a system that only does deferred promotion of irrationals.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 6, 2025, 7:06pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/46 "2025-06-06T19:06:38Z")

</div>

> [@danielwe](#):
>
> so you would indeed get different results from a system that only does deferred promotion of irrationals

That, but also the simple deferred calculation approach is orders of magnitude simpler. It is something we could have in the short run: dusting off IrrationalExpressions.jl or creating something similar is a relatively simple undertaking, but an RRA approach would take much longer I guess. (But if anyone wants to do it, that is great too).

> [@moble](#):
>
> And it looks to me like [`TypeDomainNaturalNumbers.jl`](https://gitlab.com/nsajko/TypeDomainNaturalNumbers.jl) can do that and more.

It seems to be more CAS-like, and in the type domain, with all the related advantages and disadvantages. My understanding is that the [motivation is different](https://discourse.julialang.org/t/type-domain-static-integers/118568/13), but I have not read the whole source thoroughly.

---

<div class="post-metadata">

**Author:** ![VinceNeede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vinceneede/32/215744_2.png) [@VinceNeede](https://discourse.julialang.org/u/VinceNeede)\
**Post date:** [June 6, 2025, 7:52pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/47 "2025-06-06T19:52:58Z")

</div>

> [@Tamas\_Papp](#):
>
> dusting off [IrrationalExpressions.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/IrrationalExpressions) or creating something similar is a relatively simple undertaking

That would work really well, especially if it could be done by the compiler as you mentioned.

> [@Tamas\_Papp](#):
>
> If the compiler can churn through all the constant folding, it could even be costless.

just wanted to specify that the execution of the functions themselves should not be deferred, it would give a lot of overhead, but rather their compilation. But also this I think it is not trivial, imagine something like:

```julia
logpi() = log(pi)

```

How should it behave when called with

```julia
2.0*logpi()

```

And when called as

```julia
2.0f0*logpi()

```

Should the compiler understand that the function is called with different types and compile the function in the 2 format? Would that make the sysimages too big? Should only one type be compiled and give errors if it is called with a different type? Should recursion be completely disabled?

Another possibility could be, is there a way to change how irrationals are treated when alone? For example something (variable? Environment Variable?) that I can set that would work somehow like this:

```julia
const DefaultFloat = Float64
log(x::Irrational) = log(DefaultFloat(x))

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [June 6, 2025, 8:21pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/48 "2025-06-06T20:21:57Z")

</div>

> [@VinceNeede](#):
>
> `logpi() = log(pi)`

This is why these ideas quickly turn into ad hoc, incomplete attempts at a CAS unless you’re careful. The real number API is an attempt to draw the line in a systematic and reasonable way (although it does require the judgment of where to cut off the exact symbolics and fall back to RRA, with Boehm’s approach ultimately informed by the operations available on a standard calculator (app)). Whether it’s actually a good approach to folding literal expressions, I’m not sure, and @Tamas_Papp provides good reasons against, but I’d love to see it tried out (or maybe trying it out myself at some point, but not right now).

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [June 6, 2025, 10:41pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/49 "2025-06-06T22:41:02Z")

</div>

> [@Tamas\_Papp](#):
>
> > [@moble](#):
> >
> > And it looks to me like [`TypeDomainNaturalNumbers.jl`](https://gitlab.com/nsajko/TypeDomainNaturalNumbers.jl) can do that and more.
> 
> It seems to be more CAS-like, and in the type domain, with all the related advantages and disadvantages.

Sure, everything’s in the type domain (as the package name says, too). `Irrational` is the same, as is IrrationalConstants.jl. However I’m not sure if it makes sense to compare my package to a CAS. It doesn’t rely on any of the CAS algorithms, like Groebner bases or whatnot, and the functionality is really much less than a CAS would provide. In fact, there’s no nontrivial algorithm in the package implementation, except perhaps for the continued fraction arithmetic (for rationals). The goal is basically to push the features as far as possible, generalizing `Irrational` and IrrationalConstants.jl, while letting the Julia type system do all the work.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [June 6, 2025, 10:48pm UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/50 "2025-06-06T22:48:53Z")

</div>

> [@danielwe](#):
>
> A principled approach to this, which has the desired capabilities but is also clearly bounded and not just an ad hoc, incomplete CAS, is Hans Boehm’s real number API

I looked into that paper multiple times, each time being left more disappointed. The approach hardcodes a list of allowed analytic functions, and requires arbitrary-precision floating-point arithmetic (thus it requires a dependency external library written in C, in practice) to be able to try to compare real numbers. I don’t see anything principled in that. It’s nice for a calculator app, but I’m not seeing where else could Boehm’s real number API be useful.

To be clear, TypeDomainNaturalNumbers.jl relies `BigFloat`, too. However it’s just used for converting to a finite `AbstractFloat` representation, and for checking positivity/negativity, as far as I remember. So everything is exact. Basically, my approach is less ambitious (as far as they can be compared), but more _principled_.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 7, 2025, 8:47am UTC](https://discourse.julialang.org/t/default-real-float-kind/129631/51 "2025-06-07T08:47:43Z")

</div>

> [@VinceNeede](#):
>
> just wanted to specify that the execution of the functions themselves should not be deferred, it would give a lot of overhead, but rather their compilation

If constant folding works, the execution would only be “conceptually” deferred whenever it is an argument in a function call where precision can be determined. In fact it would be determined at compile time.

In Julia it is generally not a good idea to defer compilation, and it isn’t easy either. The whole language is built around AOT compilation after all.

> [@VinceNeede](#):
>
> How should it behave when called with

Perhaps you did not read the code sketch I wrote above? The proposed specs are pretty much like IrrationalExpressions.jl.

> [@danielwe](#):
>
> hese ideas quickly turn into ad hoc, incomplete attempts at a CAS unless you’re careful

Precisely. That’s why I don’t want to do it at all 😉

I think that for most applications of scientific computing (which is the comparative advantage of Julia), RRA has the wrong cost/benefit profile. Sure, it is cute for a calculator in Android, but even there I would just go with a Common-Lisp style promotion on demand to `BigInt` and plain vanilla 64-bit floats otherwise. From a practical perspective, this was a perfect example of [nerdsniping](https://xkcd.com/356/).

[Previous page](https://discourse.julialang.org/t/default-real-float-kind/129631.md?page=2)
