zig icon indicating copy to clipboard operation
zig copied to clipboard

Ambiguous Integer Division In Float Expression

Open iacore opened this issue 2 years ago • 3 comments

Consider the following code.

const std = @import("std");

pub fn main() !void {
    var a: f32 = 0.66;
    const b = 3 / 2 / a / 2;

    std.debug.print("b={}\n", .{b});

    a = 42;
}

Both / 2 mean different things. 3 / 2 is 1.

To the compiler, this is not ambiguous. To me, this is confusing.

Given being readable is Zig's goal, I argue to make integer division forbidden in a floating point expression.

Solution 1

In the above example one would have to write

    var a: f32 = 0.66;
    const c = 3 / 2;
    const b = c / a / 2;

Solution 2

Be like Rust and force 3.0 / 2.0 / a / 2.0.

Discovery

var dt: f32 = ...;

if (dt < 1 / 30) { // is dt < 0!
    ...
}

I was used to writing / <integer constant> in a floating point expression. But, if the left side is also an integer, the meaning is different.

iacore avatar Dec 22 '23 12:12 iacore

All arithmetic operations are left-associative in most languages (C/C++/Rust/Java/Go, ...)

If you feel that reading code is ambiguous use brackets to make it explicit ((3/2)/a)/2

slonik-az avatar Dec 22 '23 13:12 slonik-az

@slonik-az The issue here is that part of the expression is evaluated using integer arithmetic and then converting to floating-point rather than all of it being performed as floating-point arithmetc. This yields an incorrect result that's difficult to spot in the above case which your suggestion shows as it still suffers from the same issue as 3/2 == 1 (not the desired 1.5).

tauoverpi avatar Dec 23 '23 11:12 tauoverpi

@tauoverpi Each subexpression is evaluated independently of others. 3/2 is integer division resulting in 1. Zig behaves exactly as C.

slonik-az avatar Dec 24 '23 09:12 slonik-az