@@ -543,7 +543,7 @@ fn try_format_exact_int_without_suffix_scaling(
543543 value : ParsedNumber ,
544544 opts : & TransformOptions ,
545545 precision : usize ,
546- ) -> Option < String > {
546+ ) -> Option < Result < String > > {
547547 if opts. to != Unit :: None {
548548 return None ;
549549 }
@@ -557,15 +557,46 @@ fn try_format_exact_int_without_suffix_scaling(
557557
558558 let scaled = integer / to_unit;
559559
560- Some ( if precision == 0 {
560+ // reject when formatted output would need 20+ digits
561+ const MAX_FORMATTED : u128 = 10_000_000_000_000_000_000 ;
562+ let precision_factor = 10_u128 . pow ( precision. min ( 19 ) as u32 ) ;
563+ if scaled
564+ . unsigned_abs ( )
565+ . checked_mul ( precision_factor)
566+ . is_none_or ( |v| v >= MAX_FORMATTED )
567+ {
568+ let value_sci = format_gnu_scientific ( scaled as f64 ) ;
569+ return Some ( Err ( format ! (
570+ "value/precision too large to be printed: '{value_sci}/{precision}' (consider using --to)"
571+ ) ) ) ;
572+ }
573+
574+ Some ( Ok ( if precision == 0 {
561575 scaled. to_string ( )
562576 } else {
563577 format ! (
564578 "{scaled}{}{}" ,
565579 locale_decimal_separator( ) ,
566580 "0" . repeat( precision)
567581 )
568- } )
582+ } ) )
583+ }
584+
585+ fn format_gnu_scientific ( v : f64 ) -> String {
586+ // 6 significant figures with trimmed trailing zeros and signed exponent
587+ let s = format ! ( "{v:.5e}" ) ;
588+ if let Some ( e_pos) = s. find ( 'e' ) {
589+ let ( mantissa, rest) = s. split_at ( e_pos) ;
590+ let exp = & rest[ 1 ..] ;
591+ let mantissa = mantissa. trim_end_matches ( '0' ) . trim_end_matches ( '.' ) ;
592+ if exp. starts_with ( '-' ) {
593+ format ! ( "{mantissa}e{exp}" )
594+ } else {
595+ format ! ( "{mantissa}e+{exp}" )
596+ }
597+ } else {
598+ s
599+ }
569600}
570601
571602fn transform_to (
@@ -577,7 +608,7 @@ fn transform_to(
577608 is_precision_specified : bool ,
578609) -> Result < String > {
579610 if let Some ( result) = try_format_exact_int_without_suffix_scaling ( s, opts, precision) {
580- return Ok ( result) ;
611+ return result;
581612 }
582613
583614 let s = s. to_f64 ( ) ;
0 commit comments