我发现了一些奇怪的东西。
此函数将数字放在给定点的数字中,并返回修改后的数字。 现在我们想做put_digit(123456789123456784,0,9); 这将在数字的末尾加上9,替换最后一个数字(4)。
这是WORKS的代码:
long long int put_digit(long long int number, char place, char digit)
{
long long int result = number;
long long int power = number;
power = pow(10, (place));
result -= get_digit(number, place)*power;
result += digit*pow(10, (place));
return result;
}
代码返回123456789123456789
这是不起作用的代码:
long long int put_digit(long long int number, char place, char digit)
{
long long int result = number;
result -= get_digit(number, place)*pow(10, (place));
result += digit*pow(10, (place));
return result;
}
此代码返回123456789123456800作为结果。
函数get_digit()返回给定位置的数字。 这是代码:
char get_digit(long long int number, char place)
{
long long int target = number;
char digit = 0;
target /= pow(10, place);
digit = target % 10;
return digit;
}
•低数字不会发生这种情况。
•get_digit()始终返回正确的值(在本例中为4)。
•get_digit()是一个char,因为它不是一个计数器函数,因此最好专注于使用更少的内存而不是使用像int这样的更快的变量。
•我尝试使用括号来避免麻烦的运算符优先级,但无济于事。
•执行put_digit(123456789123456000,2,7)时也会出现奇怪的行为,由于某种原因返回123456789123456704.这可以通过将第二个结果计算中的pow函数替换为变量“power”来解决。
我只是不明白为什么会这样。
我得到某种溢出吗?这是我的系统故障还是我自己的?我是否以糟糕的方式使用pow()?
答案 0 :(得分:4)
pow()
的声明是:double pow( double base, double exponent );
在第一种情况下:
long long int power = number;
power = pow(10, (place));
pow()
返回的值在分配long long int
时会转换为power
。其余的计算使用整数进行处理,结果就是您期望的结果。
关于第二种情况:
result -= get_digit(number, place)*pow(10, (place));
get_digit(number, place)
返回的值转换为double
,因为它需要乘以浮点数(由pow()
返回)。此外,在减去乘法结果之前,result
的值将转换为double
。最后,计算出的值从double
转换为long long int
,以存储在result
中。
但从一定幅度开始,浮点数会失去最低有效数字的精度。
尝试使用这段简单的代码自己查看:
long long int i = 123456789123456785;
for (; i <= 123456789123456795; i ++) {
printf("long long int: %lld; double: %f\n", i, (double)i);
}
输出:
long long int: 123456789123456785; double: 123456789123456784.000000
long long int: 123456789123456786; double: 123456789123456784.000000
long long int: 123456789123456787; double: 123456789123456784.000000
long long int: 123456789123456788; double: 123456789123456784.000000
long long int: 123456789123456789; double: 123456789123456784.000000
long long int: 123456789123456790; double: 123456789123456784.000000
long long int: 123456789123456791; double: 123456789123456784.000000
long long int: 123456789123456792; double: 123456789123456800.000000
long long int: 123456789123456793; double: 123456789123456800.000000
long long int: 123456789123456794; double: 123456789123456800.000000
long long int: 123456789123456795; double: 123456789123456800.000000
此行为不是错误,而是浮点数的限制。
代码的解决方案是在pow(10, place)
返回后立即将long long int
返回的值转换为result -= get_digit(number, place)*(long long int)pow(10, place);
:
animation: {
duration: 0,
onComplete: function () {
var self = this,
chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = '18px Arial';
ctx.textAlign = "center";
ctx.fillStyle = "#ffffff";
Chart.helpers.each(self.data.datasets.forEach(function (dataset, datasetIndex) {
var meta = self.getDatasetMeta(datasetIndex),
total = 0, //total values to compute fraction
labelxy = [],
offset = Math.PI / 2, //start sector from top
radius,
centerx,
centery,
lastend = 0; //prev arc's end line: starting with 0
for (var val of dataset.data) { total += val; }
Chart.helpers.each(meta.data.forEach( function (element, index) {
radius = 0.9 * element._model.outerRadius - element._model.innerRadius;
centerx = element._model.x;
centery = element._model.y;
var thispart = dataset.data[index],
arcsector = Math.PI * (2 * thispart / total);
if (element.hasValue() && dataset.data[index] > 0) {
labelxy.push(lastend + arcsector / 2 + Math.PI + offset);
}
else {
labelxy.push(-1);
}
lastend += arcsector;
}), self)
var lradius = radius * 3 / 4;
for (var idx in labelxy) {
if (labelxy[idx] === -1) continue;
var langle = labelxy[idx],
dx = centerx + lradius * Math.cos(langle),
dy = centery + lradius * Math.sin(langle),
val = Math.round(dataset.data[idx] / total * 100);
ctx.fillText(val + '%', dx, dy);
}
}), self);
}
},