问题描述
我试图在将给定对象快速转换为字符串后创建它的散列,但字符串中返回的编码值不同。
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
// The web API will only accept tokens 1) for users,and 2) having the "TestScope" scope for this API
static readonly string[] scoperequiredByApi = new string[] { "TestScope" };
[HttpGet]
public string Get()
{
HttpContext.VerifyUserHasAnyAcceptedScope(scoperequiredByApi);
return "test";
}
}
此处在 myObjectValues 中包含一个 Decimal 值 33.48。如果我尝试将此 mydata 编码为字符串,则返回的值为 33.47999999999999488。我试图将十进制值四舍五入到 2 位,但最后的字符串不断发布这个数字。我试图将它保存在字符串中,然后返回到十进制,但编码字符串中返回的值仍然是 33.479999999ish。
我不能使用字符串来计算和比较哈希值,因为从服务器返回的哈希值是 33.48,这永远不会等于我用这个长值得到的结果。
解决方法
使用基础
Decimal
值创建的 Double
值总是会产生这些问题。
Decimal
值创建的 String
值不会产生这些问题。
你可以尝试做的是 -
- 有一个私有的
String
值作为后备存储,用于安全地编码和解码这个十进制值。 - 公开另一个使用此基础
Decimal
值的计算出的String
值。
import Foundation
class Test: Codable {
// Not exposed : Only for encoding & decoding
private var decimalString: String = "33.48"
// Work with this in your app
var decimal: Decimal {
get {
Decimal(string: decimalString) ?? .zero
}
set {
decimal = newValue
decimalString = "\(newValue)"
}
}
}
do {
let encoded = try JSONEncoder().encode(Test())
print(String(data: encoded,encoding: .utf8))
// Optional("{\"decimalString\":\"33.48\"}")
let decoded = try JSONDecoder().decode(Test.self,from: encoded)
print(decoded.decimal) // 33.48
print(decoded.decimal.nextUp) // 33.49
print(decoded.decimal.nextDown) // 33.47
} catch {
print(error)
}
,
我试图在将给定对象快速转换为字符串后创建它的散列,但字符串中返回的编码值不同。
不要这样做。只是不要。这是不明智的。
我将通过类比来解释它:想象一下,如果你用六位十进制数字的精度来表示数字。你必须使用一些精度,对吗?
现在,1/3 将表示为 0.333333
。但是 2/3 将由 0.666667
表示。所以现在,如果你将 1/3 乘以 2,你将不会得到 2/3。如果你把 1/3 加到 1/3 到 1/3,你就不会得到 1。
所以 1 的哈希值会因你如何得到 1 而不同!如果你把 1/3 加到 1/3 到 1/3,你会得到一个不同于你加 2/3 到 1/3 的哈希值。
这根本不是哈希的正确数据类型。不要为此目的使用双打。舍入会起作用,直到它不起作用。
而您使用的是 33 + 48/100 -- 这个值不能以 2 为底数准确表示,就像 1/3 不能以 10 为底数准确表示一样。