![](/img/trans.png)
[英]smallest unsigned int that can contain the positive values of a given signed integral?
[英]Smallest positive multiplier that when applied to an array renders the array integral
给定一个n
非负元素的数组,在C / C ++的任何库中是否有一个函数返回最小的正乘数 ,当应用于数组的每个元素时返回一个整数?
例如,如果n=2
的数组是1.66667, 2.33333
则乘数将是3.当我们将数组的每个元素乘以3时,我们得到5, 7
,都是整数。
如果数组是8,10
,则乘数将为0.5。 这将给我们4,5
。
(1)在任何一个众所周知的库中都有一个有效的函数,如boost
, eigen
等?
(2)如果库中没有可用的东西,那么找出多个算法的有效算法是什么?
在一般情况下,您的问题没有很好的解决方案,因为这些值以具有有限精度的浮点格式存储,并且只能精确存储分母2的分数。 例如, 0.1 * 10
可能不是您平台上的整数值。
如果从整数量计算数组中的值,则应将它们表示为具有足够大小的整数对的标准化分数,并计算其分母的最小公倍数。
如果您想要问题的近似解决方案,您可以指定epsilon的值,并手动设计解决方案。 我认为没有库函数来满足这个需求,但是一个强力解决方案很容易编写:
unsigned long long ullgcd(unsigned long long a, unsigned long long b) {
/* compute the greatest common divisor using Euclid's elegant method */
if (a < b)
return ullgcd(b, a);
else
if (b == 0)
return a;
else
return ullgcd(b, a % b);
}
double least_multiple(double *a, size_t n, double epsilon) {
for (double mult = 1;; mult += 1) {
size_t i;
unsigned long long div = 0;
for (i = 0; i < n; i++) {
double d = fabs(a[i] * mult);
unsigned long long v = round(d);
if (fabs(v - d) > epsilon)
break;
div = ullgcd(v, div);
}
if (i == n)
break;
}
/* mult is the smallest non zero integer that fits your goal.
the smallest multiplier is obtained by dividing it
by the greatest common divisor of the resulting integer array.
*/
return mult / div;
}
不是你指定的方式没有。 问题是十进制值1.66667
和2.33333
没有这样的乘数:你假设的近似值来源于数学方面的任意舍入策略。
然后有浮点属性需要担心,所以你可以使用double
或float
来排除任何东西。
这里最好的选择是使用分数类来表示数字。 那么任何常见的乘数都会随着一些简单的数学而退出。
请参阅http://www.boost.org/doc/libs/1_64_0/libs/rational/index.html
看一下Rosetta Code的“将十进制数转换为有理数”。 由于我不熟悉C,我将C代码转换为Python(尽管我认为Python可能有一些相关的库)并添加了一些你可以轻松适应C的函数。如果分数转换中的分母是全部1.0
,我们除以数字列表的最大公约数。 否则,我们会返回独特分母的产品。
import math
import operator
def f(arr):
epsilon = 4
fractions = [rat_approx(i, 16**epsilon) for i in arr]
# The denominators in the fraction conversion are all 1.0
if sum([denom for (num, denom) in fractions]) == len(fractions):
return 1.0 / gcd_of_many([num for (num, denom) in fractions])
else:
# Otherwise, return the product of unique denominators
return reduce(operator.mul, set([denom for (num, denom) in fractions]), 1)
def gcd(a, b):
if a < b:
return gcd(b, a)
elif b == 0:
return a;
else:
return gcd(b, a % b)
def gcd_of_many(arr):
result = arr[0]
for i in xrange(1, len(arr)):
result = gcd(result, arr[i])
return result
# Converted from
# https://rosettacode.org/wiki/Convert_decimal_number_to_rational#C
def rat_approx(f, md):
# a: continued fraction coefficients.
h = [0, 1, 0]
k = [1, 0, 0]
n = 1
neg = 0
num = 0
denom = 0
if md <= 1:
denom = 1
num = f
return num, denom
if f < 0:
neg = 1
f = -f
while f != math.floor(f):
n <<= 1
f *= 2
d = f
# continued fraction and check denominator each step
for i in xrange(65):
a = d // n if n else 0
if i and not a:
break
x = d
d = n
n = x % n
x = a;
if k[1] * a + k[0] >= md:
x = (md - k[0]) // k[1]
if x * 2 >= a or k[1] >= md:
i = 65
else:
break
h[2] = x * h[1] + h[0]
h[0] = h[1]
h[1] = h[2]
k[2] = x * k[1] + k[0]
k[0] = k[1]
k[1] = k[2]
denom = k[1]
num = -h[1] if neg else h[1]
return (num, denom)
输出:
f([8, 10])
=> 0.5
f([1.66667, 2.33333])
=> 3.0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.