@@ -49,7 +49,7 @@ Display options:
49
49
- significant digits: 6
50
50
51
51
julia> x = interval(0.1, 0.3)
52
- [0.0999999 , 0.300001 ]_com
52
+ [0.1 , 0.3 ]_com
53
53
54
54
julia> setdisplay(:full)
55
55
Display options:
@@ -69,7 +69,7 @@ Display options:
69
69
- significant digits: 3
70
70
71
71
julia> x
72
- [0.0999 , 0.301 ]_com
72
+ [0.1 , 0.3 ]_com
73
73
74
74
julia> setdisplay(; decorations = false)
75
75
Display options:
@@ -79,7 +79,7 @@ Display options:
79
79
- significant digits: 3
80
80
81
81
julia> x
82
- [0.0999 , 0.301 ]
82
+ [0.1 , 0.3 ]
83
83
```
84
84
"""
85
85
function setdisplay (format:: Symbol = display_options. format;
@@ -196,14 +196,14 @@ function _str_basic_repr(a::BareInterval{<:AbstractFloat}, format::Symbol)
196
196
return string (str_lo, " , " , str_hi)
197
197
elseif format === :midpoint
198
198
m = mid (a)
199
- str_m = _round_string (m, sigdigits, RoundNearest )
199
+ str_m = _round_string (m, sigdigits)
200
200
# str_m = ifelse(m ≥ 0, string('+', str_m), str_m)
201
- output = string (str_m, " ± " , _round_string (radius (a), sigdigits, RoundUp ))
201
+ output = string (str_m, " ± " , _round_string (radius (a), sigdigits))
202
202
return replace (output, " Inf" => ' ∞' )
203
203
else
204
- str_lo = _round_string (lo, sigdigits, RoundDown )
204
+ str_lo = _round_string (lo, sigdigits)
205
205
# str_lo = ifelse(lo ≥ 0, string('+', str_lo), str_lo)
206
- str_hi = _round_string (hi, sigdigits, RoundUp )
206
+ str_hi = _round_string (hi, sigdigits)
207
207
# str_hi = ifelse(hi ≥ 0, string('+', str_hi), str_hi)
208
208
output = string (' [' , str_lo, " , " , str_hi, ' ]' )
209
209
return replace (output, " Inf]" => " ∞)" , " [-Inf" => " (-∞" )
@@ -231,26 +231,26 @@ function _str_basic_repr(a::BareInterval{Float32}, format::Symbol)
231
231
return string (str_lo, " , " , str_hi)
232
232
elseif format === :midpoint
233
233
m = mid (a)
234
- str_m = _round_string (m, sigdigits, RoundNearest )
234
+ str_m = _round_string (m, sigdigits)
235
235
str_m = replace (string (str_m, " f0" ), " NaNf0" => " NaN32" , " Inff0" => " Inf32" )
236
236
if contains (str_m, ' e' )
237
237
str_m = replace (str_m, ' e' => ' f' , " f0" => " " )
238
238
end
239
239
# str_m = ifelse(m ≥ 0, string('+', str_m), str_m)
240
- str_r = _round_string (radius (a), sigdigits, RoundUp )
240
+ str_r = _round_string (radius (a), sigdigits)
241
241
str_r = replace (string (str_r, " f0" ), " NaNf0" => " NaN32" , " Inff0" => " Inf32" )
242
242
if contains (str_r, ' e' )
243
243
str_r = replace (str_r, ' e' => ' f' , " f0" => " " )
244
244
end
245
245
return string (str_m, " ± " , str_r)
246
246
else
247
- str_lo = _round_string (lo, sigdigits, RoundDown )
247
+ str_lo = _round_string (lo, sigdigits)
248
248
str_lo = replace (string (' [' , str_lo, " f0" ), " NaNf0" => " NaN32" , " [-Inff0" => " (-∞" )
249
249
if contains (str_lo, ' e' )
250
250
str_lo = replace (str_lo, ' e' => ' f' , " f0" => " " )
251
251
end
252
252
# str_lo = ifelse(lo ≥ 0, string('+', str_lo), str_lo)
253
- str_hi = _round_string (hi, sigdigits, RoundUp )
253
+ str_hi = _round_string (hi, sigdigits)
254
254
str_hi = replace (string (str_hi, " f0]" ), " NaNf0" => " NaN32" , " Inff0]" => " ∞)" )
255
255
if contains (str_hi, ' e' )
256
256
str_hi = replace (str_hi, ' e' => ' f' , " f0" => " " )
@@ -274,14 +274,14 @@ function _str_basic_repr(a::BareInterval{Float16}, format::Symbol)
274
274
return replace (output, " Float16(NaN)" => " NaN16" , " Float16(-Inf)" => " -Inf16" , " Float16(Inf)" => " Inf16" )
275
275
elseif format === :midpoint
276
276
m = mid (a)
277
- str_m = _round_string (m, sigdigits, RoundNearest )
277
+ str_m = _round_string (m, sigdigits)
278
278
# str_m = ifelse(m ≥ 0, string('+', str_m), str_m)
279
- output = string (" Float16(" , str_m, " ) ± Float16(" , _round_string (radius (a), sigdigits, RoundUp ), ' )' )
279
+ output = string (" Float16(" , str_m, " ) ± Float16(" , _round_string (radius (a), sigdigits), ' )' )
280
280
return replace (output, " Float16(NaN)" => " NaN16" , " Float16(Inf)" => ' ∞' )
281
281
else
282
- str_lo = _round_string (lo, sigdigits, RoundDown )
282
+ str_lo = _round_string (lo, sigdigits)
283
283
# str_lo = ifelse(lo ≥ 0, string('+', str_lo), str_lo)
284
- str_hi = _round_string (sup (a), sigdigits, RoundUp )
284
+ str_hi = _round_string (sup (a), sigdigits)
285
285
# str_hi = ifelse(hi ≥ 0, string('+', str_hi), str_hi)
286
286
output = string (" [Float16(" , str_lo, " ), Float16(" , str_hi, " )]" )
287
287
return replace (output, " Float16(NaN)" => " NaN16" , " [Float16(-Inf)" => " (-∞" , " Float16(Inf)]" => " ∞)" )
@@ -308,102 +308,19 @@ function _str_basic_repr(a::BareInterval{<:Rational}, format::Symbol)
308
308
end
309
309
end
310
310
311
- # round to the prescribed significant digits
312
- # code inspired by `_string(x::BigFloat, k::Integer)` in base/mpfr.jl
313
-
314
- function _round_string (x:: T , sigdigits:: Int , r:: RoundingMode ) where {T<: AbstractFloat }
315
- str_x = string (x)
316
- str_digits = split (contains (str_x, ' .' ) ? split (str_x, ' .' ; limit = 2 )[2 ] : str_x, ' e' ; limit = 2 )[1 ]
317
- len = length (str_digits)
318
- if isinteger (x) && sigdigits ≥ len # `x` is exactly representable
319
- return replace (_round_string (big (x), length (str_x), RoundNearest), " e-0" => " e-" )
320
- elseif ispow2 (abs (x)) && sigdigits ≥ len # `x` is exactly representable
321
- return replace (_round_string (big (x), len + 1 , RoundNearest), " e-0" => " e-" )
322
- else
323
- return _round_string (big (x), sigdigits, r)
324
- end
325
- end
311
+ # truncate to the prescribed significant digits
326
312
327
- _round_string (x:: BigFloat , sigdigits:: Int , :: RoundingMode{:Nearest} ) =
328
- Base. MPFR. _string (x, sigdigits- 1 ) # `sigdigits-1` digits after the decimal
329
-
330
- function _round_string (x:: BigFloat , sigdigits:: Int , r:: RoundingMode )
331
- if ! isfinite (x)
332
- return string (Float64 (x))
333
- else
334
- str_x = string (x)
335
- str_digits = split (split (str_x, ' .' ; limit = 2 )[2 ], ' e' ; limit = 2 )[1 ]
336
- len = length (str_digits)
337
- if isinteger (x) && sigdigits ≥ len # `x` is exactly representable
338
- return _round_string (big (x), length (str_x), RoundNearest)
339
- elseif ispow2 (abs (x)) && sigdigits ≥ len # `x` is exactly representable
340
- return _round_string (big (x), len + 1 , RoundNearest)
341
- else
342
- # `sigdigits` digits after the decimal
343
- str = Base. MPFR. string_mpfr (x, " %.$(sigdigits) Re" )
344
- rounded_str = _round_string (str, r)
345
- return Base. MPFR. _prettify_bigfloat (rounded_str)
346
- end
347
- end
313
+ function _round_string (x:: AbstractFloat , sigdigits:: Int )
314
+ ! isfinite (x) && return string (x)
315
+ max_sig_digits = _count_sigdigits (string (x))
316
+ ndigits = min (sigdigits, max_sig_digits)
317
+ str = Printf. @sprintf (" %.*g" , ndigits, x)
318
+ occursin (r" [eE]" , str) && return replace (str, r" ^([+-]?\d +)(?=[eE])" => s "\1 .0" , r" ([eE][+-])0+(\d +)" => s "\1\2 " )
319
+ ! occursin (r" \. " , str) && return str * " .0"
320
+ return str
348
321
end
349
322
350
- _round_string (s:: String , :: RoundingMode{:Up} ) =
351
- startswith (s, ' -' ) ? string (' -' , _round_string_down (s[2 : end ])) : _round_string_up (s)
352
-
353
- _round_string (s:: String , :: RoundingMode{:Down} ) =
354
- startswith (s, ' -' ) ? string (' -' , _round_string_up (s[2 : end ])) : _round_string_down (s)
355
-
356
- function _round_string_up (s:: String )
357
- # `s` has one extra significant digit to control the rounding
358
- mantissa, exponent = eachsplit (s, ' e' )
359
- mantissa = mantissa[1 : end - 1 ]
360
- len = length (mantissa)
361
- idx = findlast (d -> (d != = ' 9' ) & (d != = ' .' ), mantissa)
362
- if idx == len # last significant digit is not `9`
363
- d = parse (Int, mantissa[len]) + 1 # increase the last significant digit
364
- return string (view (mantissa, 1 : len- 1 ), d, ' e' , exponent)
365
- else
366
- if isnothing (idx) # all significant digits are `9`
367
- expo = parse (Int, exponent) + 1 # increase the exponent by `1`
368
- expo_str = string (expo; pad = 2 )
369
- exponent = expo < 0 ? expo_str : string (' +' , expo_str)
370
- return string (" 1." , ' 0' ^ (len - 2 ), ' e' , exponent)
371
- else
372
- new_mantissa = string (
373
- view (mantissa, 1 : idx- 1 ),
374
- parse (Int, mantissa[idx]) + 1 ,
375
- # add `"."` if the last significant digit not equal to `9` is before the decimal point
376
- idx == 1 ? " ." : " " ,
377
- ' 0' ^ (len - idx))
378
- return string (new_mantissa, ' e' , exponent)
379
- end
380
- end
381
- end
382
-
383
- function _round_string_down (s:: String )
384
- # `s` has one extra significant digit to control the rounding
385
- mantissa, exponent = eachsplit (s, ' e' )
386
- len = length (mantissa)
387
- idx = findlast (d -> (d != = ' 0' ) & (d != = ' .' ), mantissa)
388
- if idx == len # last significant digit is not `0`
389
- return string (view (mantissa, 1 : len- 1 ), ' e' , exponent) # truncate
390
- else
391
- if isnothing (idx) # all significant digits are `0`
392
- expo = parse (Int, exponent) - 1 # decrease the exponent by `1`
393
- expo_str = string (expo; pad = 2 )
394
- exponent = expo < 0 ? expo_str : string (' +' , expo_str)
395
- return string (" 9." , ' 9' ^ (len - 3 ), ' e' , exponent)
396
- else
397
- new_mantissa = string (
398
- view (mantissa, 1 : idx- 1 ),
399
- parse (Int, mantissa[idx]) - 1 ,
400
- # add `"."` if the last significant digit not equal to `0` is before the decimal point
401
- idx == 1 ? " ." : " " ,
402
- ' 9' ^ (len - (idx + 1 )))
403
- return string (new_mantissa, ' e' , exponent)
404
- end
405
- end
406
- end
323
+ _count_sigdigits (s:: AbstractString ) = length (replace (split (s, r" [eE]" )[1 ], ' -' => " " , ' .' => " " , r" ^0+" => " " ))
407
324
408
325
#
409
326
0 commit comments