@@ -348,6 +348,19 @@ fn round_to_precision(digits: &mut String, precision: usize) -> bool {
348348 }
349349}
350350
351+ fn fractional_digits_for_precision ( num : f64 , precision : usize ) -> usize {
352+ let exponent = format ! ( "{num:e}" )
353+ . rsplit_once ( 'e' )
354+ . and_then ( |( _, exp) | exp. parse :: < isize > ( ) . ok ( ) )
355+ . unwrap_or_default ( ) ;
356+
357+ if exponent. is_negative ( ) {
358+ exponent. unsigned_abs ( ) . saturating_add ( precision) . saturating_add ( 1 )
359+ } else {
360+ 100
361+ }
362+ }
363+
351364/// Mimics JavaScript's `Number.prototype.toPrecision()` method
352365///
353366/// The `toPrecision()` method returns a string representing the Number object to the specified precision.
@@ -391,8 +404,10 @@ pub fn to_precision(mut num: f64, precision: usize) -> String {
391404 suffix = "0" . repeat ( precision) ;
392405 exponent = 0 ;
393406 } else {
394- // Format with maximum precision to get all digits
395- suffix = format ! ( "{num:.100}" ) ;
407+ // For very small numbers (e.g. 3e-308), we need more than 100 fractional digits
408+ // to keep enough significant digits for precision comparison.
409+ let fractional_digits = fractional_digits_for_precision ( num, precision) ;
410+ suffix = format ! ( "{num:.fractional_digits$}" ) ;
396411
397412 // Calculate exponent
398413 exponent = flt_str_to_exp ( & suffix) ;
@@ -519,6 +534,7 @@ fn test() {
519534 "const a = Infinity" ,
520535 "const a = 480.00" ,
521536 "const a = -30.00" ,
537+ "const x = 3e-308" ,
522538 "(1000000000000000128).toFixed(0)" ,
523539 ] ;
524540
0 commit comments