Cannot create negative zero in NBT
The bug
It is not possible to create -0.0f/-0.0d in NBT, because 0.0f/0.0d is created instead. This prevents objects in memory containing negative zero from being accurately serialized.
It was possible to create negative zero before 19w38b. However, it became impossible to create them since 19w39a due to NBT caching.
Furthermore, if the Named Binary Tag specification (formerly at http://www.minecraft.net/docs/NBT.txt) is still valid, this behavior would violate the Payload specification for TAG_Float/TAG_Double: A floating point value (32 bits, big endian, IEEE 754-2008, binary32) / A floating point value (64 bits, big endian, IEEE 754-2008, binary64).
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f
/data get storage mc-171881: float
Expected behavior
Storage mc-171881: has the following contents: -0.0f
Actual behavior
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d
/data get storage mc-171881: double
Expected behavior
Storage mc-171881: has the following contents: -0.0d
Actual behavior
Storage mc-171881: has the following contents: 0.0d
Code analysis
Since +0.0 and -0.0 are considered identical in IEEE 754, ZERO (the cached 0.0) is returned when value is -0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }
- Unresolved
intsuc- 7
- 4
- Confirmed
- Commands
- nbt
1.15.2 - 25w04a
1.15.2 20w06a 20w07a 20w08a 20w09a 20w11a 20w12a 20w14a 20w16a 20w17a 20w18a 20w20b 1.16-pre5 1.16.1 20w27a 1.16.2-pre1 1.16.2 1.16.3 1.16.4-pre1 1.16.4 20w45a 20w46a 20w48a 20w49a 20w51a 21w03a 1.16.5 21w05b 21w08b 21w10a 21w11a 21w13a 21w15a 21w16a 21w19a 1.17-pre1 1.17 1.17.1 21w37a 1.18.1 22w03a 22w05a 1.18.2-pre1 1.18.2 22w11a 22w12a 1.19 1.19.1 1.19.2 1.19.3-rc1 1.19.3-rc2 1.19.3 23w03a 23w05a 23w06a 1.19.4-pre3 1.19.4 23w12a 23w13a 23w14a 23w16a 23w17a 23w18a 1.20-pre4 1.20-rc1 1.20 1.20.1 23w31a 23w32a 23w33a 1.20.2 23w42a 23w46a 1.20.4 24w03a 24w04a 24w14a 1.21 24w33a 1.21.1 1.21.4 25w04a
Created Issue:
-0.0 cannot be represented in NBT
The bug
The NBT tags -0.0f and -0.0d is converted to 0.0f and 0.0d respectively.
How to reproduce
/data modify storage _ float set value -0.0f/data get storage _ float→
Storage minecraft:_ has the following contents: 0.0f
/data modify storage _ double set value -0.0d/data get storage _ double→
Storage minecraft:_ has the following contents: 0.0d
Code analysis
Since signed zeros are identical (+0.0 == -0.0) in IEEE 754, the cached 0.0 is always returned.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d
isconverted to 0.0f and 0.0d respectively.How to reproduce
/data modify storage _ float set value -0.0f /data get storage _ float→
Storage minecraft:_ has the following contents: 0.0f
/data modify storage _ double set value -0.0d /data get storage _ double→
Storage minecraft:_ has the following contents: 0.0d
Code analysis
Since signed zeros are identical (+0.0 == -0.0) in IEEE 754, the cached 0.0 is always returned.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d are converted to 0.0f and 0.0d respectively.
How to reproduce
/data modify storage _ float set value -0.0f /data get storage _ float→
Storage minecraft:_ has the following contents: 0.0f
/data modify storage _ double set value -0.0d /data get storage _ double→
Storage minecraft:_ has the following contents: 0.0d
Code analysis
Since signed zeros are identical (+0.0 == -0.0) in IEEE 754, the cached 0.0 is always returned.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d are converted to 0.0f and 0.0d respectively.
How to reproduce
/data modify storage _ float set value -0.0f /data get storage _ float→
Storage minecraft:_ has the following contents: 0.0f
/data modify storage _ double set value -0.0d /data get storage _ double→
Storage minecraft:_ has the following contents: 0.0d
Code analysis
Since signed zeros are identical (+0.0 == -0.0) in IEEE 754, the cached 0.0 is
alwaysreturned.// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d are converted to 0.0f and 0.0d respectively.
How to reproduce
/data modify storage _ float set value -0.0f /data get storage _ float→
Storage minecraft:_ has the following contents: 0.0f
/data modify storage _ double set value -0.0d /data get storage _ double→
Storage minecraft:_ has the following contents: 0.0d
Code analysis
Since signed zeros are identical (+0.0 == -0.0) in IEEE 754, the cached 0.0 is returned instead of -0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d are converted to 0.0f and 0.0d respectively.
How to reproduce
/data modify storage _ float set value -0.0f /data get storage _ float→
Storage minecraft:_ has the following contents: 0.0f
/data modify storage _ doubleset value -0.0d /data get storage_double→
Storage m
inecraft:_has the following contents: 0.0dCode analysis
Si
nce signed zeros are identical (+0.0 == -0.0) in IEEE 754, the cached0.0is returned instead of-0.0.// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d are converted to 0.0f and 0.0d respectively and cannot be constructed.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, 0.0 is returned instead of -0.0 since value is equal to ZERO (the cached 0.0).
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d are converted to 0.0f and 0.0d respectively and cannot be constructed.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, 0.0 is returned instead of -0.0 since value is equal to ZERO (the cached 0.0
).// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) {returnvalue==0.0d ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d are converted to 0.0f and 0.0d respectively and cannot be constructed.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is equal to 0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }should be
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d
are converted to0.0f and 0.0d respectively and cannot be constructed.How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is equal to 0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }should be
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d cannot be constructed because 0.0f and 0.0d are constructed instead, respectively.
Objects that contain negative zeros in memory are not precisely serialized.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is equal to 0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }should be
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d cannot be constructed because 0.0f and 0.0d are constructed instead, respectively.
Objects that contain negative zeros in memory are not precisely serialized.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is equal to 0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }should be
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d cannot be constructed because 0.0f and 0.0d are constructed instead, respectively. This makes floating-point numbers in NBT strange ones that lack only the negative zeros compared to floating-point numbers in Java. Also, objects that contain negative zeros in memory not to be precisely serialized.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is equal to 0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The code above should be:
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d cannot be constructed because 0.0f and 0.0d are constructed instead, respectively. This makes floating-point numbers in NBT strange ones that lack only the negative zeros compared to floating-point numbers in Java
. Also,objects that contain negative zeros in memory not to be precisely serialized.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is equal to 0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The code above should be:
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d cannot be constructed because 0.0f and 0.0d are constructed instead, respectively. This makes the floating-point numbers in NBT strange ones that lack only the negative zeros compared to the floating-point numbers in Java and objects that contain negative zeros in memory not to be precisely serialized to NBT.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is equal to 0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The code above should be:
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }
The bug
The NBT tags -0.0f and -0.0d cannot be constructed because 0.0f and 0.0d are constructed instead, respectively. This makes
the floating-point numbers in NBT strange ones that lack only the negative zeros compared to the floating-point numbers in Java andobjects that contain negative zeros in memory not to be precisely serialized to NBT.
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0 since value is
equal to0.0.// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The code above should be:
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }The bug
The NBT tags -0.0f and -0.0d cannot be constructed because 0.0f and 0.0d are constructed instead, respectively. This makes objects that contain negative zeros in memory not to be precisely serialized to NBT.
How to reproduce
If an internal value is negative zero, the prefix - should be printed.
Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysis
Signed zeros are identical (+0.0 == -0.0) in IEEE 754. If value is -0.0, ZERO (the cached 0.0) is returned instead of -0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The code above should be:
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return Double.compare(value, 0.0d) == 0 ? ZERO : new DoubleTag(value); }
-0.0cannot be represented in NBTNegative zero cannot be represented in NBT
The bug
The NBT tags -0.0f
and-0.0dcannot be constructedbecause 0.0fand0.0dare constructed instead, respectively. This makes objectsthatcontain negative zeros in memory not to be precisely serializedto NBT.How to reproduce
If an internal value is negative zero, the prefix- should be printed.Float tags
/data modify storage mc-171881: float set value -0.0f /data get storage mc-171881: float→
Storage mc-171881: has the following contents: 0.0f
Double tags
/data modify storage mc-171881: double set value -0.0d /data get storage mc-171881: double→
Storage mc-171881: has the following contents: 0.0d
Code analysisSigned zeros are identical (+0.0 == -0.0) in IEEE 754. If value is
-0.0,ZERO (the cached 0.0) is returnedinstead of-0.0.// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The code above should be:
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return Float.compare(value, 0.0f) == 0 ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { returnDouble.compare(value, 0.0d)== 0 ? ZERO : new DoubleTag(value); }The bug
It is not possible to create -0.0f/-0.0d in NBT, because 0.0f/0.0d is created instead. This prevents objects in memory containing negative zero from being accurately serialized.
Furthermore, if the Named Binary Tag specification (formerly at http://www.minecraft.net/docs/NBT.txt) is still valid, this behavior would violate the Payload specification for TAG_Float/TAG_Double: A floating point value (32 bits, big endian, IEEE 754-2008, binary32) / A floating point value (64 bits, big endian, IEEE 754-2008, binary64).
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f
/data get storage mc-171881: floatExpected behavior
Storage mc-171881: has the following contents: -0.0fActual behavior
Storage mc-171881: has the following contents: 0.0fDouble tags
/data modify storage mc-171881: double set value -0.0d
/data get storage mc-171881: doubleExpected behavior
Storage mc-171881: has the following contents: -0.0dActual behavior
Storage mc-171881: has the following contents: 0.0dCode analysis
Since +0.0 and -0.0 are considered identical in IEEE 754, ZERO (the cached 0.0) is returned when value is -0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }
Negative zero cannot be representedin NBTCannot create negative zero in NBT
The bug
It is not possible to create -0.0f/-0.0d in NBT, because 0.0f/0.0d is created instead. This prevents objects in memory containing negative zero from being accurately serialized.
Furthermore, if the Named Binary Tag specification (formerly at
http://www.minecraft.net/docs/NBT.txt) is still valid, this behavior would violate the Payload specification for TAG_Float/TAG_Double:A floating point value (32 bits, big endian, IEEE 754-2008, binary32)/ A floating point value (64 bits, big endian, IEEE 754-2008, binary64).How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f
/data get storage mc-171881: floatExpected behavior
Storage mc-171881: has the following contents: -0.0fActual behavior
Storage mc-171881: has the following contents: 0.0fDouble tags
/data modify storage mc-171881: double set value -0.0d
/data get storage mc-171881: doubleExpected behavior
Storage mc-171881: has the following contents: -0.0dActual behavior
Storage mc-171881: has the following contents: 0.0dCode analysis
Since +0.0 and -0.0 are considered identical in IEEE 754, ZERO (the cached 0.0) is returned when value is -0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }The bug
It is not possible to create -0.0f/-0.0d in NBT, because 0.0f/0.0d is created instead. This prevents objects in memory containing negative zero from being accurately serialized.
It was possible to create negative zero before 19w38b. However, it became impossible to create them since 19w39a due to NBT caching.
Furthermore, if the Named Binary Tag specification (formerly at http://www.minecraft.net/docs/NBT.txt) is still valid, this behavior would violate the Payload specification for TAG_Float/TAG_Double: A floating point value (32 bits, big endian, IEEE 754-2008, binary32) / A floating point value (64 bits, big endian, IEEE 754-2008, binary64).
How to reproduce
Float tags
/data modify storage mc-171881: float set value -0.0f
/data get storage mc-171881: floatExpected behavior
Storage mc-171881: has the following contents: -0.0fActual behavior
Storage mc-171881: has the following contents: 0.0fDouble tags
/data modify storage mc-171881: double set value -0.0d
/data get storage mc-171881: doubleExpected behavior
Storage mc-171881: has the following contents: -0.0dActual behavior
Storage mc-171881: has the following contents: 0.0dCode analysis
Since +0.0 and -0.0 are considered identical in IEEE 754, ZERO (the cached 0.0) is returned when value is -0.0.
// net.minecraft.nbt.FloatTag public static FloatTag valueOf(float value) { return value == 0.0f ? ZERO : new FloatTag(value); } // net.minecraft.nbt.DoubleTag public static DoubleTag valueOf(double value) { return value == 0.0d ? ZERO : new DoubleTag(value); }
In what scenario would it be useful to have a distinction between 0.0 and -0.0? I'm partially referencing tickets like
MC-153454, which have been resolved as invalid.Though I'm not sure about the usefulness of the distinction it's unnatural that the floating-point representation used in NBT doesn't match that used in Java. I want to clarify the specification of negative zero in NBT.
seems to be someone misunderstanding that the XYZ line of the debug screen corresponds to the player's coordinates as an entity (which logically starts with -0 when between 0 and -1) and not the coordinates of a block (which would not make sense to start with -0). However, there's still an underlying bug in the F3 menu related to a true -0 in the XYZ line, so I've added a comment to that issue.MC-153454With that in mind, this issue is different because it's about conformance to IEEE floating point specifications rather than about whether something is possible or makes logical sense for any specific data tag.
Regarding usefulness, while it may not be a useful distinction in vanilla, it'd be quite useful for datapacks to be able to set an otherwise impossible NBT value that doesn't cause immediate errors like Infinityd or -Infinityd (possible via setting the value to 1.79769313486232E+308d). This could potentially be used as an error condition or something similar if it's possible to test for 0.0 vs -0.0
Edit: Also, I apparently have no idea how to properly link an issue.