我正在写一个函数将数字四舍五入到两个地方.当我试图围绕特定值时,我发现了一个错误.所以,我运行了代码:
class Program {
static void Main(string[] args) {
int limit = 100;
for (int number = 0; number <= limit; number++) {
Console.WriteLine((System.Math.Round((double)(number+0.995),2,MidpointRounding.AwayFromZero)));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我发现: 8.99 9.99 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 32.99 33.99 34.99 35.99 36.99 37.99 38.99 39.99
数字未四舍五入到下一个值.
当我运行相同的代码直到1500:我得到数字:
8.99 9.99 32.99 33.99 38.99 35.99 36.99 37.99 38.99 39.99 1024.99 1025.99 1026.99 1027.99 1028.99 1029.99 1030.99 1031.99 1032.99 1033.99 1034.99 1035.99 1036.99 1032.99 1033.99 1039.99 1040.99 1012.99 1012.99 1033.99 1033.99 1039.99 1045.99 1066.99 1012.99 1079.99 1039.99 1033.99 1039.99 1025.99 1025.99 1025.99 1025.99 1039.99 1025.99 1066.99 1066.99 1065.99 1064.99 1065.99 1066.99 1067.99 1068.99 1069.99 1070.99 1071.99 1072.99 1073.99 1074.99 1075.99 1076.99 1077.99 1078.99 1079.99 1080.99 1081.99 1082.99 1083.99 1084.99 1085.99 1086.99 1087.99 1088.99 1089.99 1090.99 1091.99 1092.99 1093.99 1094.99 1095.99 1096.99 1097.99 1098.99 1099.99 1100.99 1101.99 1102.99 1103.99 1104.99 1105.99 1106.99 1107.99 1108.99 1109.99 1110.99 1111.99 1112.99 1113.99 1114.99 1115.99 1116.99 1117.99 1118.99 1119.99 1120.99 1121.99 1122.99 1123.99 1124.99 1125.99 1126.99 1127.99 1128.99 1129.99 1130.99 1131.99 1132.99 1133.99 1134.99 1135.99 1136.99 1137.99 1138.99 1139.99 1140.99 1141.99 1142.99 1143.99 1144.99 1145.99 1146.99 1147.99 1148.99 1149.99 1150.99 1151.99 1152.99 1153.99 1154.99 1155.99 1156.99 1157.99 1158.99 1159.99 1160.99 1161.99 1162.99 1163.99 1164.99 1165.99 1166.99 1167.99 1168.99 1169.99 1170.99 1171.99 1172.99 1173.99 1174.99 1175.99 1176.99 1177.99 1178.99 1179.99 1180.99 1181.99 1182.99 1183.99 1184.99 1185.99 1186.99 1187.99 1188.99 1189.99 1190.99 1191.99 1192.99 1193.99 1194.99 1195.99 1196.99 1197.99 1198.99 1199.99 1200.99 1201.99 1202.99 1203.99 1204.99 1205.99 1206.99 1207.99 1208.99 1209.99 1210.99 1211.99 1212.99 1213.99 1214.99 1215.99 1216.99 1217.99 1218.99 1219.99 1220.99 1221.99 1222.99 1223.99 1224.99 1225.99 1226.99 1227.99 1228.99 1229.99 1230.99 1231.99 1232.99 1233.99 1234.99 1235.99 1236.99 1237.99 1238.99 1239.99 1240.99 1241.99 1242.99 1243.99 1244.99 1245.99 1246.99 1247.99 1248.99 1249.99 1250.99 1251.99 1252.99 1253.99 1254.99 1255.99 1256.99 1257.99 1258.99 1259.99 1260.99 1261.99 1262.99 1263.99 1264.99 1265.99 1266.99 1267.99 1268.99 1269.99 1270.99 1271.99 1272.99 1273.99 1274.99 1275.99 1276.99 1277.99 1278.99 1279.99 1280.99 1281.99 1282.99 1283.99 1284.99 1285.99 1286.99 1287.99 1288.99 1289.99 1290.99 1291.99 1292.99 1293.99 1294.99 1295.99 1296.99 1297.99 1298.99 1299.99 1300.99 1301.99 1302.99 1303.99 1304.99 1305.99 1306.99 1307.99 1308.99 1309.9999 1259.99 1260.99 1261.99 1262.99 1263.99 1264.99 1265.99 1266.99 1267.99 1268.99 1269.99 1270.99 1279.99 1277.99 1279.99 1279.99 1275.99 1288.99 1288.99 1288.99 1288.99 1288.99 1288.99 1288.99 1288.99 1289.99 1299.99 1292.99 1293.99 1293.99 1299.99 1295.99 1292.99 1297.99 1298.99 1299.99 1299.99 1299.99 1299.99 1299.99 1299.99 130.99.99 1301.99 1302.99 1303.99 1304.99 1305.99 1306.99 1307.99 1308.99 1309.9999 1259.99 1260.99 1261.99 1262.99 1263.99 1264.99 1265.99 1266.99 1267.99 1268.99 1269.99 1270.99 1279.99 1277.99 1279.99 1279.99 1275.99 1288.99 1288.99 1288.99 1288.99 1288.99 1288.99 1288.99 1288.99 1289.99 1299.99 1292.99 1293.99 1293.99 1299.99 1295.99 1292.99 1297.99 1298.99 1299.99 1299.99 1299.99 1299.99 1299.99 1299.99 130.99.99 1301.99 1302.99 1303.99 1304.99 1305.99 1306.99 1307.99 1308.99 1309.99
哪些没有四舍五入到下一个数字!有没有人知道为什么它会发生这些特定的数字!
Jon*_*eet 10
问题在于,当你取"number + 0.995"的值时,由于二进制浮点的正常原因不能精确地表示十进制值,所以这不会完全是数字+ 0.995.
有些受害者会稍微过一点,有时它会有点不足.如果它不足,并将结果舍入到两位小数,则最终得到"0.99"位.Math.Round尝试在某种程度上考虑到这一点是可能的,但我不确定具体细节.
解决方案 - 在可能的情况下 - 是用来decimal代替十进制数字很重要的double东西.
有关更多信息,请参阅我在.NET中关于二进制浮点和十进制浮点的文章.
这是一个程序,使用我的DoubleConverter代码,显示添加0.995后的不准确性:
using System;
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
double d = i + 0.995;
Console.WriteLine(DoubleConverter.ToExactString(d));
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
0.99499999999999999555910790149937383830547332763671875 1.99500000000000010658141036401502788066864013671875 2.99500000000000010658141036401502788066864013671875 3.99500000000000010658141036401502788066864013671875 4.99500000000000010658141036401502788066864013671875 5.99500000000000010658141036401502788066864013671875 6.99500000000000010658141036401502788066864013671875 7.99500000000000010658141036401502788066864013671875 8.9949999999999992184029906638897955417633056640625 9.9949999999999992184029906638897955417633056640625 10.9949999999999992184029906638897955417633056640625 11.9949999999999992184029906638897955417633056640625 12.9949999999999992184029906638897955417633056640625 13.9949999999999992184029906638897955417633056640625 14.9949999999999992184029906638897955417633056640625 15.9949999999999992184029906638897955417633056640625 16.995000000000000994759830064140260219573974609375 17.995000000000000994759830064140260219573974609375 18.995000000000000994759830064140260219573974609375 19.995000000000000994759830064140260219573974609375 20.995000000000000994759830064140260219573974609375 ...
(注意虽然它开始在8点开始走0.994,但它仍然持续到15 - 而Math.Round在10点"修正"自己.)
| 归档时间: |
|
| 查看次数: |
693 次 |
| 最近记录: |