mojira.dev
MC-123388

"execute store" on "double" data types uses only 'float' rather than 'double' precision in intermediate scale calculation

go into a world in creative, fly

/scoreboard objectives add ReturnX dummy
/tp @p 2097150.3 200.0 0.0
/execute store result score @s ReturnX run data get entity @s Pos[0] 1024.0
/summon area_effect_cloud ~ ~ ~ {Duration:1000,Tags:["return_loc"],Rotation:[20f,20f]}
/execute store result entity @e[limit=1,tag=return_loc] Pos[0] double 0.0009765625 run scoreboard players get @p ReturnX
/execute as @e[limit=1,tag=return_loc] at @s run tp @p ~ ~ ~

Expected: press F3 and see that the player's coordinate still ends in ".3"
Actual: player's coordinate now ends in ".25"

The behavior is what one would get if the intermediate 'scale factor' in the store were using single-precision rather than double-precision floating point, which I expect is the source of the bug. (double-precision has plenty of significant digits to recover the precise value)

Implications for gameplay: you can use this technique of storing a player's coords in the scoreboard to tp them somewhere and then return them to their exact position. However, due to the precision bug, players standing next to a wall get returned to a slightly different position and suffocate in the wall.

EDIT

Here is a simpler-to-understand repro

go into creative, fly, run

summon pig ~ ~ ~ {NoAI:1b,Tags:["piggy"]}

then run a function:

scoreboard objectives add Score dummy
scoreboard objectives setdisplay sidebar Score
tp @p 1.23456789012345 200 0
execute store result score @p Score run data get entity @p Pos[0] 1000000000.0
execute store result entity @e[tag=piggy,limit=1] Pos[0] double 0.000000001 run data get entity @p Pos[0] 1000000000.0
execute store result score @e[tag=piggy,limit=1] Score run data get entity @e[tag=piggy,limit=1] Pos[0] 1000000000.0

Expected:
both guys have score 1234567890
Actual:
pig has score 1234567880

The 1234567880 wrong result is what you get when doing a 32-bit (single-precision) float calculation, whereas the 1234567890 correct result is what you get when doing a 64-bit (double-precision) calculation. And Pos[0] is a double, and called out as "double" in the command.

Attachments

Comments 7

This may possibly be related to MC-123390

You can see in

[media]

, that scale is read as float and not converted to a double.
This can be seen with the following command too, where the scale is an invalid float, but a valid double.

/execute store result entity @e[type=!player,limit=1] SomeTag double 100000000000000000000000000000000000000000000000 run say a

Possibly easier reproduction steps to prove that no conversion of the scale happens are:

  1. Give yourself an item and throw it on the ground

    /give @s stone{Test:1.0}
  2. Run the following commands

    /scoreboard players set #largeValue test 1000000000
    /execute store result entity @e[type=item,limit=1] Item.tag.Test double 100000000000000000 run scoreboard players get #largeValue test
    /data get entity @e[type=item,limit=1]

To verify the result the following Java code could be used

System.out.println(String.format(java.util.Locale.ROOT,"%.0f", 1000000000 * 100000000000000000.0f));
System.out.println(String.format(java.util.Locale.ROOT,"%.0f", 1000000000 * (double)100000000000000000.0f));

May I change the report and replace your reproduction steps with the one listed above?

Why not? Your reproduction steps require you being at a certain position.

Could you then at least clean up your report please?

This is indeed fixed, great.

If I perform the command:
/execute store result storage test UUID long 1 run data get entity @p UUIDMost
The value stored will be truncated to the size of int, then casted to a long.

I feel like this bug is related to this ticket. Not sure if this one should be reopened or a new ticket should be created, since it is very similar. (This bug occurred in 20w10a)

That is not a bug, commands are only capable of returning values of type int, which is a limitation hardcoded into brigadier. 

This use case is part of why `data modify` was added, which is capable of copying between two NBT locations without going via brigadier, allowing the data to remain unchanged

Brian McNamara

Nathan Adams

Confirmed

/execute, /execute-store

Minecraft 17w50a

Minecraft 18w01a

Retrieved