@@ -91,6 +91,28 @@ index 75d4d0937f1e39fe630b1318a4ad531de7fbd644..d0ae9a7c3b20de44cb202390cc0dfd4d
9191 if (content != null) {
9292 out.write(content.getBytes(StandardCharsets.UTF_8));
9393 }
94+ diff --git a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
95+ index 5448e7900953da79b2bc01f99fd7e8f3080148e7..b509376a6dbc3780f7c14c631bf51b7fc24aa50d 100644
96+ --- a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
97+ +++ b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
98+ @@ -35,6 +35,8 @@ public interface IFernflowerPreferences {
99+ String IGNORE_INVALID_BYTECODE = "iib";
100+ String VERIFY_ANONYMOUS_CLASSES = "vac";
101+
102+ + String STANDARDIZE_FLOATING_POINT_NUMBERS = "sfn";
103+ +
104+ String LOG_LEVEL = "log";
105+ String MAX_PROCESSING_METHOD = "mpm";
106+ String RENAME_ENTITIES = "ren";
107+ @@ -81,6 +83,8 @@ public interface IFernflowerPreferences {
108+ defaults.put(IGNORE_INVALID_BYTECODE, "0");
109+ defaults.put(VERIFY_ANONYMOUS_CLASSES, "0");
110+
111+ + defaults.put(STANDARDIZE_FLOATING_POINT_NUMBERS, "1");
112+ +
113+ defaults.put(LOG_LEVEL, IFernflowerLogger.Severity.INFO.name());
114+ defaults.put(MAX_PROCESSING_METHOD, "0");
115+ defaults.put(RENAME_ENTITIES, "0");
94116diff --git a/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java b/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java
95117index fad1ddcfb9d2e43720b4cd3acaa165ba86e94892..cf03900654e427bd435ba6dc2d5a0cec8c8708e4 100644
96118--- a/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java
@@ -332,15 +354,15 @@ index 82ae0a25a20d2727f611d359e699d6666d1e0ae4..a86f0d2887c6c19cb1d911ec43830eb6
332354
333355 return res;
334356diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java
335- index caa160fdc4ff5954b0976b11d81177278ae79ab6..e6363319573d157f5878dfdd93f8e60b44facb64 100644
357+ index caa160fdc4ff5954b0976b11d81177278ae79ab6..39df4ddd7afa01bba116063323630e514679a01f 100644
336358--- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java
337359+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java
338360@@ -216,7 +216,7 @@ public class ConstExprent extends Exprent {
339361 else if (floatVal == Float.NEGATIVE_INFINITY) {
340362 yield new TextBuffer("-1.0F / 0.0F");
341363 }
342364- yield new TextBuffer(value.toString()).append('F');
343- + yield new TextBuffer(trimZeros(value .toString() )).append('F');
365+ + yield new TextBuffer(trimFloat(Float .toString(floatVal), floatVal )).append('F');
344366 }
345367 case CodeConstants.TYPE_DOUBLE -> {
346368 double doubleVal = (Double)value;
@@ -360,24 +382,98 @@ index caa160fdc4ff5954b0976b11d81177278ae79ab6..e6363319573d157f5878dfdd93f8e60b
360382+ yield new TextBuffer("-1.0D / 0.0D");
361383 }
362384- yield new TextBuffer(value.toString());
363- + yield new TextBuffer(trimZeros(value .toString() )).append('D');
385+ + yield new TextBuffer(trimDouble(Double .toString(doubleVal), doubleVal )).append('D');
364386 }
365387 case CodeConstants.TYPE_NULL -> new TextBuffer("null");
366388 case CodeConstants.TYPE_OBJECT -> {
367- @@ -273,6 +273,18 @@ public class ConstExprent extends Exprent {
389+ @@ -273,6 +273,92 @@ public class ConstExprent extends Exprent {
368390 };
369391 }
370392
371- + // Different JVM implementations/version display Floats and Doubles with different number of trailing zeros.
372- + // This trims them all down to only the necessary amount.
373- + private static String trimZeros(String value) {
374- + int i = value.length() - 1;
375- + while (i >= 0 && value.charAt(i) == '0') {
376- + i--;
393+ + // Different JVM implementations/version display Floats and Doubles with different String representations
394+ + // for the same thing. This trims them all down to only the necessary amount.
395+ + private static String trimFloat(String value, float start) {
396+ + // Includes NaN and simple numbers
397+ + if (value.length() <= 3 || !DecompilerContext.getOption(IFernflowerPreferences.STANDARDIZE_FLOATING_POINT_NUMBERS))
398+ + return value;
399+ +
400+ + String exp = "";
401+ + int eIdx = value.indexOf('E');
402+ + if (eIdx != -1) {
403+ + exp = value.substring(eIdx);
404+ + value = value.substring(0, eIdx);
405+ + }
406+ +
407+ + // Cut off digits that don't affect the value
408+ + String temp = value;
409+ + int dotIdx = value.indexOf('.');
410+ + do {
411+ + value = temp;
412+ + temp = value.substring(0, value.length() - 1);
413+ + } while (!temp.isEmpty() && !"-".equals(temp) && Float.parseFloat(temp + exp) == start);
414+ +
415+ + if (dotIdx != -1 && value.indexOf('.') == -1) {
416+ + value += ".0";
417+ + } else if (dotIdx != -1) {
418+ + String integer = value.substring(0, dotIdx);
419+ + String decimal = value.substring(dotIdx + 1);
420+ +
421+ + String rounded = (Integer.parseInt(integer) + 1) + ".0" + exp;
422+ + if (Float.parseFloat(rounded) == start)
423+ + return rounded;
424+ +
425+ + long decimalVal = 1;
426+ + for (int i = 0; i < decimal.length() - 1; i++) {
427+ + decimalVal = (decimalVal - 1) * 10 + decimal.charAt(i) - '0' + 1;
428+ + rounded = integer + '.' + decimalVal + exp;
429+ + if (Float.parseFloat(rounded) == start)
430+ + return rounded;
377431+ }
378- + if (value.charAt(i) == '.')
379- + i++;
380- + return value.substring(0, i + 1);
432+ + }
433+ +
434+ + return value + exp;
435+ + }
436+ +
437+ + private static String trimDouble(String value, double start) {
438+ + // Includes NaN and simple numbers
439+ + if (value.length() <= 3 || !DecompilerContext.getOption(IFernflowerPreferences.STANDARDIZE_FLOATING_POINT_NUMBERS))
440+ + return value;
441+ +
442+ + String exp = "";
443+ + int eIdx = value.indexOf('E');
444+ + if (eIdx != -1) {
445+ + exp = value.substring(eIdx);
446+ + value = value.substring(0, eIdx);
447+ + }
448+ +
449+ + // Cut off digits that don't affect the value
450+ + String temp = value;
451+ + int dotIdx = value.indexOf('.');
452+ + do {
453+ + value = temp;
454+ + temp = value.substring(0, value.length() - 1);
455+ + } while (!temp.isEmpty() && !"-".equals(temp) && Double.parseDouble(temp + exp) == start);
456+ +
457+ + if (dotIdx != -1 && value.indexOf('.') == -1) {
458+ + value += ".0";
459+ + } else if (dotIdx != -1) {
460+ + String integer = value.substring(0, dotIdx);
461+ + String decimal = value.substring(dotIdx + 1);
462+ +
463+ + String rounded = (Long.parseLong(integer) + 1) + ".0" + exp;
464+ + if (Double.parseDouble(rounded) == start)
465+ + return rounded;
466+ +
467+ + long decimalVal = 1;
468+ + for (int i = 0; i < decimal.length() - 1; i++) {
469+ + decimalVal = (decimalVal - 1) * 10 + decimal.charAt(i) - '0' + 1;
470+ + rounded = integer + '.' + decimalVal + exp;
471+ + if (Double.parseDouble(rounded) == start)
472+ + return rounded;
473+ + }
474+ + }
475+ +
476+ + return value + exp;
381477+ }
382478+
383479 private boolean inConstantVariable(String classSignature, String variableName) {
0 commit comments