Mojira Archive
MC-171881

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

  1. /data modify storage mc-171881: float set value -0.0f
  1. /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

  1. /data modify storage mc-171881: double set value -0.0d
  1. /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);
}