Skip to content

Commit 4d0f94f

Browse files
bicycle1885johanmon
authored andcommitted
make Printf's general format C11 compliant
1 parent 069877e commit 4d0f94f

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

stdlib/Printf/src/Printf.jl

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,28 @@ const __BIG_FLOAT_MAX__ = 8192
475475
elseif T == Val{'f'} || T == Val{'F'}
476476
newpos = Ryu.writefixed(buf, pos, x, prec, plus, space, hash, UInt8('.'))
477477
elseif T == Val{'g'} || T == Val{'G'}
478+
# C11-compliant general format
478479
prec = prec == 0 ? 1 : prec
479-
x = round(x, sigdigits=prec)
480-
newpos = Ryu.writeshortest(buf, pos, x, plus, space, hash, prec, T == Val{'g'} ? UInt8('e') : UInt8('E'), true, UInt8('.'))
480+
# format the value in scientific notation and parse the exponent part
481+
exp = let p = Ryu.writeexp(buf, pos, x, prec)
482+
b1, b2, b3, b4 = buf[p-4], buf[p-3], buf[p-2], buf[p-1]
483+
Z = UInt8('0')
484+
if b1 == UInt8('e')
485+
# two-digit exponent
486+
sign = b2 == UInt8('+') ? 1 : -1
487+
exp = 10 * (b3 - Z) + (b4 - Z)
488+
else
489+
# three-digit exponent
490+
sign = b1 == UInt8('+') ? 1 : -1
491+
exp = 100 * (b2 - Z) + 10 * (b3 - Z) + (b4 - Z)
492+
end
493+
flipsign(exp, sign)
494+
end
495+
if -4 exp < prec
496+
newpos = Ryu.writefixed(buf, pos, x, prec - (exp + 1), plus, space, hash, UInt8('.'), !hash)
497+
else
498+
newpos = Ryu.writeexp(buf, pos, x, prec - 1, plus, space, hash, T == Val{'g'} ? UInt8('e') : UInt8('E'), UInt8('.'), !hash)
499+
end
481500
elseif T == Val{'a'} || T == Val{'A'}
482501
x, neg = x < 0 || x === -Base.zero(x) ? (-x, true) : (x, false)
483502
newpos = pos

stdlib/Printf/test/runtests.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,14 @@ end
449449
@test Printf.@sprintf("%e", 1) == "1.000000e+00"
450450
@test Printf.@sprintf("%g", 1) == "1"
451451

452+
# issue #39748
453+
@test Printf.@sprintf("%.16g", 194.4778127560983) == "194.4778127560983"
454+
@test Printf.@sprintf("%.17g", 194.4778127560983) == "194.4778127560983"
455+
@test Printf.@sprintf("%.18g", 194.4778127560983) == "194.477812756098302"
456+
@test Printf.@sprintf("%.1g", 1.7976931348623157e308) == "2e+308"
457+
@test Printf.@sprintf("%.2g", 1.7976931348623157e308) == "1.8e+308"
458+
@test Printf.@sprintf("%.3g", 1.7976931348623157e308) == "1.8e+308"
459+
452460
# escaped '%'
453461
@test_throws ArgumentError @sprintf("%s%%%s", "a")
454462
@test @sprintf("%s%%%s", "a", "b") == "a%b"

0 commit comments

Comments
 (0)