从另一个浮点数中减去 Float.MIN_VALUE 在 android 应用程序中没有影响
subtracting Float.MIN_VALUE from another float number has no effect in android application
我正在开发一个 android 应用程序,该应用程序的一部分有 2 个浮点值,我不能让它们完全相同,因为这会导致我的其中一个屏幕出现错误.这些数字是从服务器发送的,不受我的控制(例如,我不能强制它们不同)。
该应用程序是用 Kotlin 编写的,但我认为此问题与 Java 类似(如果不完全相同),因为 Kotlin 在幕后使用 JVM。
我想到了一种“创造性”的方法来解决这个问题,而又不会过多改变我的逻辑,方法是从其中一个中减去 Float.MIN_VALUE
,使它们几乎 ,但不完全是 一样。我真正需要做的是 if(a == b)
失败(b
实际上是 a - Float.MIN_VALUE
)。
但令我惊讶的是,当代码运行时,if(a == b)
returns true
。当我在 Android Studio 中打开“评估”window 时,我发现了以下内容:
让我重申一下 currentPayment
是一个 Float
,所以不应该进行任何自动转换或舍入(比如将 Float
除以 Int
例如)。
我还要指出,我可以保证 currentPayment
不是
Float.MAX_VALUE
或 -Float.MAX_VALUE
(因此运算结果在 Float
的范围内)。
根据文档, Float.MIN_VALUE
是 Float
的最小正非零值,值为 1.4E-45
,此处确认:
我在另一个post中也看到了(不知为何又找不到了),这也可以认为是Float
的最大精度,这是有道理的。
因为 currentPayment
是一个 Float
,我希望它应该能够在 [=19= 的范围内保存 any 浮点值] 到它的最大精度(即 Float.MIN_VALUE
)。
因此我希望 currentPayment
到 NOT 等于 currentPayment - Float.MIN_VALUE
,但事实并非如此。
谁能解释一下?
Since currentPayment
is a Float
, I would expect it should be able to hold any floating point value within the bounds of Float
to it's maximum precision (i.e. Float.MIN_VALUE
).
这是一个错误的假设。浮点数之所以称为“float”,是因为它具有浮点精度。精确度取决于您存储的数字有多大。最小可能的浮点值比几乎任何其他可能数字的精度都小,所以如果你加或减它,它太小而不会影响它们。在高端,浮点数的精度比整数 1 大得多。如果从 Float.MAX_VALUE
中减去 999,000,000,它仍然会 return Float.MAX_VALUE
因为精度太差了最高端。
此外,由于浮点数不以 10 为基数存储,因此它们不适合存储货币金额,因为您永远无法准确表示小数。 (我提到是因为你的变量名里面有“payment”这个词,这是一个危险信号。)
您应该使用 BigDecimal、Long 或 Int 来表示货币,这样您的货币数量和算法将是准确的。
编辑:
这是一个有助于理解它的类比,因为很难考虑二进制数。在 Java 和 Kotlin 中,浮点数是 32 位的,但想象一下我们有一种特殊的计算机可以以 10 进制存储浮点数。这台电脑上的每一位不只是0或1,而是可以是0到9之间的任何值。这台电脑上的Float可以有4位数字和一个小数位,但小数位是浮动的,所以它可以放在相对于四位数。所以这台计算机上的 Float 总是五位——其中四位是数字,第五位告诉你小数点的位置。
在这个假想的计算机的Float中,可以表示的最小可能数是.0001
,最大可能数是9999.
。您不能表示 9999.5
甚至 1000.5
,因为没有足够的可用数字。没有固定的精度——精度取决于当前数字中小数点的位置。小数点位置越靠左的数字精度越高。
为了使数字存储格式能够具有固定精度,我们必须将所有数字的小数点固定在一个位置。我们将不得不选择一个精度。假设我们选择了 0.001
的精度。我们的第五位告诉我们小数点在浮点数中的位置,现在可以只用于第五位数字。现在我们知道精度是always0.001
,但是我们能表示的最大可能数是99.999
,最小可能数是0.001
,a可能的范围比浮点小得多。此限制是使用浮点数的原因。
我正在开发一个 android 应用程序,该应用程序的一部分有 2 个浮点值,我不能让它们完全相同,因为这会导致我的其中一个屏幕出现错误.这些数字是从服务器发送的,不受我的控制(例如,我不能强制它们不同)。
该应用程序是用 Kotlin 编写的,但我认为此问题与 Java 类似(如果不完全相同),因为 Kotlin 在幕后使用 JVM。
我想到了一种“创造性”的方法来解决这个问题,而又不会过多改变我的逻辑,方法是从其中一个中减去 Float.MIN_VALUE
,使它们几乎 ,但不完全是 一样。我真正需要做的是 if(a == b)
失败(b
实际上是 a - Float.MIN_VALUE
)。
但令我惊讶的是,当代码运行时,if(a == b)
returns true
。当我在 Android Studio 中打开“评估”window 时,我发现了以下内容:
让我重申一下 currentPayment
是一个 Float
,所以不应该进行任何自动转换或舍入(比如将 Float
除以 Int
例如)。
我还要指出,我可以保证 currentPayment
不是
Float.MAX_VALUE
或 -Float.MAX_VALUE
(因此运算结果在 Float
的范围内)。
根据文档,Float.MIN_VALUE
是 Float
的最小正非零值,值为 1.4E-45
,此处确认:
我在另一个post中也看到了(不知为何又找不到了),这也可以认为是Float
的最大精度,这是有道理的。
因为 currentPayment
是一个 Float
,我希望它应该能够在 [=19= 的范围内保存 any 浮点值] 到它的最大精度(即 Float.MIN_VALUE
)。
因此我希望 currentPayment
到 NOT 等于 currentPayment - Float.MIN_VALUE
,但事实并非如此。
谁能解释一下?
Since
currentPayment
is aFloat
, I would expect it should be able to hold any floating point value within the bounds ofFloat
to it's maximum precision (i.e.Float.MIN_VALUE
).
这是一个错误的假设。浮点数之所以称为“float”,是因为它具有浮点精度。精确度取决于您存储的数字有多大。最小可能的浮点值比几乎任何其他可能数字的精度都小,所以如果你加或减它,它太小而不会影响它们。在高端,浮点数的精度比整数 1 大得多。如果从 Float.MAX_VALUE
中减去 999,000,000,它仍然会 return Float.MAX_VALUE
因为精度太差了最高端。
此外,由于浮点数不以 10 为基数存储,因此它们不适合存储货币金额,因为您永远无法准确表示小数。 (我提到是因为你的变量名里面有“payment”这个词,这是一个危险信号。)
您应该使用 BigDecimal、Long 或 Int 来表示货币,这样您的货币数量和算法将是准确的。
编辑: 这是一个有助于理解它的类比,因为很难考虑二进制数。在 Java 和 Kotlin 中,浮点数是 32 位的,但想象一下我们有一种特殊的计算机可以以 10 进制存储浮点数。这台电脑上的每一位不只是0或1,而是可以是0到9之间的任何值。这台电脑上的Float可以有4位数字和一个小数位,但小数位是浮动的,所以它可以放在相对于四位数。所以这台计算机上的 Float 总是五位——其中四位是数字,第五位告诉你小数点的位置。
在这个假想的计算机的Float中,可以表示的最小可能数是.0001
,最大可能数是9999.
。您不能表示 9999.5
甚至 1000.5
,因为没有足够的可用数字。没有固定的精度——精度取决于当前数字中小数点的位置。小数点位置越靠左的数字精度越高。
为了使数字存储格式能够具有固定精度,我们必须将所有数字的小数点固定在一个位置。我们将不得不选择一个精度。假设我们选择了 0.001
的精度。我们的第五位告诉我们小数点在浮点数中的位置,现在可以只用于第五位数字。现在我们知道精度是always0.001
,但是我们能表示的最大可能数是99.999
,最小可能数是0.001
,a可能的范围比浮点小得多。此限制是使用浮点数的原因。