Stream: beginners

Topic: Floating point arithmetic


view this post on Zulip Andy Ferris (May 02 2024 at 13:50):

I'm new to Roc with a numerics background. I'm used to things like 1.0 / 0.0 being Infinity and 0.0 / 0.0 being NaN. Does Roc use IEEE754 floating point arithmetic? Is it defaulting to the decimal type? (And is the decimal type supposed to be a floating-point value with decimal digits (mantissa) instead of binary digits? Or an integer with fixed point semantics?)

view this post on Zulip Brendan Hansknecht (May 02 2024 at 14:33):

Default fractional type is a fixed point decimal

view this post on Zulip Brendan Hansknecht (May 02 2024 at 14:34):

Can just specify the type to get a float though

view this post on Zulip Brendan Hansknecht (May 02 2024 at 14:34):

1.0f32 / 0.0

view this post on Zulip Richard Feldman (May 02 2024 at 14:57):

also type inference takes care of that automatically; if you have a function that expects a F64 or F32, you can pass it 1.0 or even just 1 and it will use the appropriate representation

view this post on Zulip Andy Ferris (May 02 2024 at 22:34):

Awesome - thanks, that makes a lot of sense.

Is there any syntax (i.e. literals) for Infinity, -Infinity and NaN of F32 and F64? The printing of these values at the REPL isn't round-trippable.

view this post on Zulip Luke Boswell (May 02 2024 at 22:36):

I don't there is. I'm interested to know what round-trippable means?

view this post on Zulip Richard Feldman (May 02 2024 at 22:56):

I assume as in what the repl prints out can't be put back into the program

view this post on Zulip Richard Feldman (May 02 2024 at 22:57):

we should probably make Num.infinityF32 and Num.infinityF64 and same for nan

view this post on Zulip Richard Feldman (May 02 2024 at 22:57):

we can't give them the type Frac * because Dec doesn't have infinity and nan

view this post on Zulip Richard Feldman (May 02 2024 at 22:58):

also probably don't need a negative infinity because e.g. -Num.infinityF64 would compile to that anyway

view this post on Zulip Andy Ferris (May 02 2024 at 23:24):

Yes I meant what printed in the REPL for at least built-in primitive types like F64 and F32 should be valid syntax for the same value. (In fact, for a functional language it should be possible to ensure this for basically all values, though you might not want to print everything in full at the REPL by default).

view this post on Zulip Andy Ferris (May 02 2024 at 23:24):

Note that being round-trippable for finite floating-point numbers is also pretty big deal. Back in the 2000's, say, a lot of languages would not give the exact same float when you print it and then parse it again, which causes trouble for really basic interchange like saving and loading a CSV or trying to debug a problem or whatever. Nowadays there exist fast and robust techniques for printing and parsing floats, so that shouldn't be a problem, but I didn't look into how Roc does this yet.

view this post on Zulip Andy Ferris (May 02 2024 at 23:27):

Richard Feldman said:

also probably don't need a negative infinity because e.g. -Num.infinityF64 would compile to that anyway

I'd suggest following whatever Roc does for -1.0. Is that evaluated as -(1.0) or parsed as a single literal?

view this post on Zulip Richard Feldman (May 02 2024 at 23:40):

made an issue! https://github.com/roc-lang/roc/issues/6709

view this post on Zulip Richard Feldman (May 02 2024 at 23:41):

Andy Ferris said:

Yes I meant what printed in the REPL for at least built-in primitive types like F64 and F32 should be valid syntax for the same value. (In fact, for a functional language it should be possible to ensure this for basically all values, though you might not want to print everything in full at the REPL by default).

in the case of opaque types it's very important that this property not hold, and for functions it's probably more annoying than helpful (especially long functions), but yeah for structural types other than functions I agree!

view this post on Zulip Andy Ferris (May 17 2024 at 13:07):

I've made a little bit more progress on this at https://github.com/roc-lang/roc/pull/6755, but am a little stuck.

Part of my problem is now cargo build isn't working (on WSL2) as it is complaining about the llvm-sys crate not being able to find LLVM. I tried apt installing llvm-dev but that wasn't helpful. The end result is I haven't been able to run my changes locally.

view this post on Zulip Anton (May 20 2024 at 13:21):

This may help:

wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 16

Add export LLVM_SYS_160_PREFIX=/usr/lib/llvm-16 to your ~/.bashrc or equivalent file for your shell.

Although I would recommend using nix with nix develop as that will set up everything for you.

view this post on Zulip Andy Ferris (May 21 2024 at 12:06):

Thanks that helps. I also had to install libpolly-16-dev and libzstd-dev.

I tried nix develop and it originally worked (a couple of weeks ago) but now it isn't, not sure what I've done differently.

view this post on Zulip Anton (May 21 2024 at 12:39):

I tried nix develop and it originally worked (a couple of weeks ago) but now it isn't, not sure what I've done differently.

You may need to do cargo clean because problems arise when rust tries to combine old cached build artifacts (outside nix) with new ones built inside nix.


Last updated: Jul 06 2025 at 12:14 UTC