Bug 29556

Summary: ecvt rounding in edge-cases is broken
Product: glibc Reporter: Gabriel Ravier <gabravier>
Component: mathAssignee: Not yet assigned to anyone <unassigned>
Status: UNCONFIRMED ---    
Severity: normal Keywords: std-posix
Priority: P2    
Version: 2.36   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Gabriel Ravier 2022-09-08 08:17:13 UTC
int main()
{
    int decpt, sign;
    char *result = ecvt(999999999999.9, 3, &decpt, &sign);

    printf("ecvt(999999999999.9, 3, &[%d], &[%d]) = '%s'\n", decpt, sign, result);
}

I believe the following program should output either:

ecvt(999999999999.9, 3, &[13], &[0]) = '100'

or:

ecvt(999999999999.9, 3, &[12], &[0]) = '999'

glibc instead outputs this:

ecvt(999999999999.9, 3, &[13], &[0]) = '1000'

which seems like it can't possibly be correct considering the call explicitly asked for 3 characters to be printed.

PS: This seems to be caused by different in rounding between what `ecvt` determines and what `fcvt` determines in the inner call to it by `ecvt`
Comment 1 Gabriel Ravier 2022-09-08 08:21:25 UTC
PS: I've tested this on:
- the original BSD implementation of ecvt
- Cosmopolitan's ecvt 
- musl's ecvt (which happens to have the same issue as glibc but in fcvt instead :p)
- OpenBSD's ecvt
- Windows's ecvt
- ReactOS's ecvt
- UNIX v10's ecvt
- Illumos's ecvt
- ELKS's ecvt

and they all returned either 100 or 999
Comment 2 Andreas Schwab 2022-09-08 10:04:46 UTC
fcvt (9.999999999999, 2,,) has the same problem, that is what ecvt eventually calls.
Comment 3 Gabriel Ravier 2022-09-08 12:35:53 UTC
Hmmmm, I'm not sure fcvt's behavior is by itself a bug, as POSIX leaves the rounding behavior of `fcvt` implementation-defined.