@@ -298,57 +298,28 @@ public void updateKnuthSamplingRate(double rate) {
298298 }
299299
300300 /**
301- * Formats a sampling rate with up to 6 significant digits and no trailing zeros, matching
302- * {@code %.6g} semantics (fixed notation for values in [1e-4, 1], scientific for smaller).
301+ * Formats a sampling rate with up to 6 decimal digits of precision and no trailing zeros.
302+ *
303+ * <p>Values below 0.0000005 (which round to zero at 6 decimal places) return {@code "0"}.
304+ * Values at or above 0.9999995 return {@code "1"}.
303305 *
304306 * <p>Uses char-array arithmetic to avoid {@link java.util.Formatter} allocations entirely.
305307 */
306308 static String formatKnuthSamplingRate (double rate ) {
307309 if (rate <= 0.0 ) return "0" ;
308310 if (rate >= 1.0 ) return "1" ;
309311
310- if (rate < 1e-4 ) {
311- return formatScientific6g (rate );
312- }
313-
314- return formatFixed6g (rate );
315- }
316-
317- /** Fixed notation for rates in [1e-4, 1): "0.DDDDDDDDD" with trailing zeros trimmed. */
318- private static String formatFixed6g (double rate ) {
319- // Choose a multiplier so Math.round(rate * multiplier) is a 6-significant-figure integer.
320- // For rate in [10^-k, 10^-(k-1)) the first sig fig is at decimal position k, so we need
321- // k+5 total fractional digits:
322- // [0.1, 1.0) -> scale=6, multiplier=1e6
323- // [0.01, 0.1) -> scale=7, multiplier=1e7
324- // [0.001, 0.01) -> scale=8, multiplier=1e8
325- // [1e-4, 0.001) -> scale=9, multiplier=1e9
326- final int scale ;
327- final long multiplier ;
328- if (rate >= 0.1 ) {
329- scale = 6 ;
330- multiplier = 1_000_000L ;
331- } else if (rate >= 0.01 ) {
332- scale = 7 ;
333- multiplier = 10_000_000L ;
334- } else if (rate >= 0.001 ) {
335- scale = 8 ;
336- multiplier = 100_000_000L ;
337- } else {
338- scale = 9 ;
339- multiplier = 1_000_000_000L ;
340- }
341-
342- long rounded = Math .round (rate * multiplier );
312+ // Round to 6 decimal places.
313+ long rounded = Math .round (rate * 1_000_000L );
343314 if (rounded == 0 ) return "0" ;
344- if (rounded >= multiplier ) return "1" ; // rounding pushed value to 1.0
315+ if (rounded >= 1_000_000L ) return "1" ;
345316
346- // Build "0." + <scale digits> and trim trailing zeros in a single right-to-left pass.
347- char [] buf = new char [2 + scale ];
317+ // Build "0.DDDDDD" and trim trailing zeros in a single right-to-left pass.
318+ char [] buf = new char [8 ]; // "0." + 6 digits
348319 buf [0 ] = '0' ;
349320 buf [1 ] = '.' ;
350321 int end = 2 ; // exclusive end; updated on first non-zero digit found from the right
351- for (int i = 2 + scale - 1 ; i >= 2 ; i --) {
322+ for (int i = 7 ; i >= 2 ; i --) {
352323 int d = (int ) (rounded % 10 );
353324 rounded /= 10 ;
354325 buf [i ] = (char ) ('0' + d );
@@ -360,72 +331,6 @@ private static String formatFixed6g(double rate) {
360331 return new String (buf , 0 , end );
361332 }
362333
363- /** Scientific notation for rates below 1e-4: "X.XXXXXe-YY" with mantissa zeros trimmed. */
364- private static String formatScientific6g (double rate ) {
365- // Normalize to [1, 10) by repeated multiply — at most ~15 iterations for realistic rates.
366- int exp = 0 ;
367- double normalized = rate ;
368- while (normalized < 1.0 ) {
369- normalized *= 10 ;
370- exp --;
371- }
372-
373- // Round mantissa to 6 significant figures (integer in [100000, 999999]).
374- long sig = Math .round (normalized * 100000.0 );
375- if (sig >= 1000000 ) {
376- sig /= 10 ;
377- exp ++;
378- if (exp >= -4 ) {
379- // Rounding pushed the value into fixed-notation range (always exactly 0.0001).
380- return "0.0001" ;
381- }
382- }
383-
384- // Build "X.XXXXXe-YY" trimming mantissa trailing zeros.
385- // Max: "X.XXXXXe-XXX" = 13 chars.
386- char [] buf = new char [13 ];
387- int pos = 0 ;
388-
389- // Integer part (always a single digit 1-9).
390- buf [pos ++] = (char ) ('0' + (int ) (sig / 100000 ));
391- sig %= 100000 ;
392-
393- // Fractional part (5 digits, trim trailing zeros).
394- if (sig > 0 ) {
395- buf [pos ++] = '.' ;
396- char [] frac = new char [5 ];
397- int fracEnd = 0 ;
398- for (int i = 4 ; i >= 0 ; i --) {
399- frac [i ] = (char ) ('0' + (int ) (sig % 10 ));
400- sig /= 10 ;
401- if (frac [i ] != '0' && fracEnd == 0 ) {
402- fracEnd = i + 1 ;
403- }
404- }
405- for (int i = 0 ; i < fracEnd ; i ++) {
406- buf [pos ++] = frac [i ];
407- }
408- }
409-
410- // Exponent: "e-YY" (always negative here, at least 2 digits).
411- buf [pos ++] = 'e' ;
412- buf [pos ++] = '-' ;
413- int absExp = -exp ;
414- if (absExp < 10 ) {
415- buf [pos ++] = '0' ;
416- buf [pos ++] = (char ) ('0' + absExp );
417- } else if (absExp < 100 ) {
418- buf [pos ++] = (char ) ('0' + absExp / 10 );
419- buf [pos ++] = (char ) ('0' + absExp % 10 );
420- } else {
421- buf [pos ++] = (char ) ('0' + absExp / 100 );
422- buf [pos ++] = (char ) ('0' + (absExp / 10 ) % 10 );
423- buf [pos ++] = (char ) ('0' + absExp % 10 );
424- }
425-
426- return new String (buf , 0 , pos );
427- }
428-
429334 TagValue getKnuthSamplingRateTagValue () {
430335 return knuthSamplingRateTagValue ;
431336 }
0 commit comments