[英]How should I fix these garbage values?
I am an apprentice of C language, trying to learn some stuff here.我是C语言的学徒,想在这里学习一些东西。 I had confronted with a problem, and I wish I could have solved it on my own.我遇到了一个问题,我希望我能自己解决它。 But, I am a short wrapper and quite prone to procrastination, so I need your good support.但是,我是一个矮小的包装工,很容易拖延,所以我需要你的大力支持。 As the title explicitly says, I do not know why my topMatches() function is spitting out some random float values, printing out at the beginning and the end of an array of scores[].正如标题明确指出的那样,我不知道为什么我的 topMatches() function 会吐出一些随机浮点值,在 scores[] 数组的开头和结尾打印出来。 Like this,像这样,
Output #1
(-0.00000, Lisa Rose),(0.99124, Gene Seymour),(0.92447, Michael Phillips),(0.89341, Claudia Puig),(0.66285, Mick LaSalle),(0.38125, Jack Matthews),(-1.00000, Toby)
Output #2
(107185664961793568883398204719104.00000, Lisa Rose),(0.99124, Gene Seymour),(0.92447, Michael Phillips),(0.89341, Claudia Puig),(0.66285, Mick LaSalle),(0.38125, Jack Matthews),(-1.00000, Toby)
Output #3
(0.99124, Lisa Rose),(0.92447, Gene Seymour),(0.89341, Michael Phillips),(0.66285, Claudia Puig),(0.38125, Mick LaSalle),(-118195603315995709432961818167345152.00000, Jack Matthews),(-1.00000, Toby)
...
The value should be in the range of -1 and 1. I would really appreciate to see your feedback.该值应在 -1 和 1 的范围内。非常感谢您的反馈。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
//data types
struct mInfo
{
char mName[20];
float rating;
};
struct cInfo
{
char name[20];
struct mInfo movi[7];
};
//prototype fxns
typedef double (*sim_fp)(struct cInfo *, const char *, const char *);
double sim_D(struct cInfo *prefs, const char *person1, const char *person2);
void topMatches(sim_fp fp, struct cInfo *prefs, const char *person1, int num);
int cmpFxn (const void * a, const void * b);
void reverseFxn(float arr[], int num);
int main()
{
int num = 7;
struct cInfo critics[num];
critics[0] = (struct cInfo) {"Lisa Rose", {"Lady in the Water", 2.5, "Snakes on a Plane", 3.5, "Just My Luck", 3, "Superman Returns", 3.5, "The Night Listener", 3, "You, Me and Dupree", 2.5}};
critics[1] = (struct cInfo) {"Gene Seymour",{"Lady in the Water", 3, "Snakes on a Plane", 3.5, "Just My Luck", 1.5, "Superman Returns", 5, "The Night Listener", 3, "You, Me and Dupree", 3.5}};
critics[2] = (struct cInfo) {"Michael Phillips",{"Lady in the Water", 2.5, "Snakes on a Plane", 3, "Superman Returns", 3.5, "The Night Listener", 4}};
critics[3] = (struct cInfo) {"Claudia Puig",{"Snakes on a Plane", 3.5, "Just My Luck", 3, "Superman Returns", 4, "The Night Listener", 4.5, "You, Me and Dupree", 2.5}};
critics[4] = (struct cInfo) {"Mick LaSalle",{"Lady in the Water", 3, "Snakes on a Plane", 4, "Just My Luck", 2, "Superman Returns", 3, "The Night Listener", 3, "You, Me and Dupree", 2}};
critics[5] = (struct cInfo) {"Jack Matthews",{"Lady in the Water", 3, "Snakes on a Plane", 4, "Superman Returns", 5, "You, Me and Dupree", 3.5}};
critics[6] = (struct cInfo) {"Toby",{"Snakes on a Plane", 4.5, "Superman Returns", 4, "You, Me and Dupree",1}};
topMatches(sim_D, critics, "Toby", 7);
return 0;
}
double sim_D(struct cInfo *prefs, const char *person1, const char *person2)
{
int i=0;
int x=0;
int next=0;
int p1;
int p2;
float X = 0;
float Y = 0;
float sumSq1 = 0;
float sumSq2 = 0;
float pSum = 0;
float num = 0;
float den = 0;
float Pscore = 0;
int nElements =0;
for (i=0;i<7;i++) {
if(strcmp(prefs[i].name, person1) ==0)
{
p1 = i;
}
else if(strcmp(prefs[i].name, person2) ==0)
{
p2 = i;
}
}
for (x=0;x<7;x++) {
for (next=0;next<7;next++)
{
if (!prefs[p1].movi[x].rating && !prefs[p2].movi[next].rating);
else if (strcmp(prefs[p1].movi[x].mName, prefs[p2].movi[next].mName) == 0)
{
X += prefs[p1].movi[x].rating;
Y += prefs[p2].movi[next].rating;
sumSq1 += pow(prefs[p1].movi[x].rating,2);
sumSq2 += pow(prefs[p2].movi[next].rating,2);
pSum += (prefs[p1].movi[x].rating*prefs[p2].movi[next].rating);
nElements++;
}
}
next = 0;
}
num = pSum-(X*Y/nElements);
den=sqrt((sumSq1-pow(X,2)/nElements)*(sumSq2-pow(Y,2)/nElements));
if(den ==0) return -1;
Pscore = num/den;
return Pscore;
}
void topMatches(sim_fp fp, struct cInfo *prefs, const char *person1, int num)
{
float scores[8];
char *buf;
int i=0;
for (i=0;i<num;i++)
{
if(strcmp(person1, prefs[i].name)==0)
{
continue;
}
scores[i] = fp(prefs, person1, prefs[i].name);
}
qsort(scores, num, sizeof(float), (*cmpFxn));
reverseFxn(scores, num);
printf("\n\n");
for(i=0;i<num;i++)
{
if (i == num-1)
{
printf("(%.5f, %s)", scores[num-1], prefs[num-1].name);
}
else
{
printf("(%.5f, %s),", scores[i], prefs[i].name);
}
}
}
void reverseFxn(float arr[], int num)
{
float scoresTmp[num];
int j;
for(j=0;j<num;j++)
{
scoresTmp[num-1-j] = arr[j];
}
for(j=0;j<num;j++)
{
arr[j]=scoresTmp[j];
}
}
int cmpFxn (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
The value of each elements of the scores[] array needs to be within the range of -1 and 1. scores[] 数组的每个元素的值需要在 -1 到 1 的范围内。
struct cInfo
you have a member struct mInfo movi[7];
在struct cInfo
你有一个成员struct mInfo movi[7];
but assign between 3 and 6 of these in main()
.但在main()
中分配其中的 3 到 6 个。 By switching from assignment to initialization those records that are not explicit set will be zero initialized.通过从赋值切换到初始化,那些未显式设置的记录将被零初始化。 This seems to be sufficient to get consistent output.这似乎足以获得一致的 output。int main() {
struct cInfo critics[] = {
{"Lisa Rose", {
{"Lady in the Water", 2.5},
{"Snakes on a Plane", 3.5},
{"Just My Luck", 3},
{"Superman Returns", 3.5},
{"The Night Listener", 3},
{"You, Me and Dupree", 2.5}
}},
{"Gene Seymour", {
{"Lady in the Water", 3},
{"Snakes on a Plane", 3.5},
{"Just My Luck", 1.5},
{"Superman Returns", 5},
{"The Night Listener", 3},
{"You, Me and Dupree", 3.5}
}},
{"Michael Phillips", {
{"Lady in the Water", 2.5},
{"Snakes on a Plane", 3},
{"Superman Returns", 3.5},
{"The Night Listener", 4}
}},
{"Claudia Puig", {
{"Snakes on a Plane", 3.5},
{"Just My Luck", 3},
{"Superman Returns", 4},
{"The Night Listener", 4.5},
{"You, Me and Dupree", 2.5}
}},
{"Mick LaSalle", {
{"Lady in the Water", 3},
{"Snakes on a Plane", 4},
{"Just My Luck", 2},
{"Superman Returns", 3},
{"The Night Listener", 3},
{"You, Me and Dupree", 2}
}},
{"Jack Matthews", {
{"Lady in the Water", 3},
{"Snakes on a Plane", 4},
{"Superman Returns", 5},
{"You, Me and Dupree", 3.5}
}},
{"Toby", {
{"Snakes on a Plane", 4.5},
{"Superman Returns", 4},
{"You, Me and Dupree",1}
}}
};
topMatches(sim_D, critics, "Toby", sizeof critics / sizeof *critics);
}
and here is example output:这是示例 output:
(0.99124, Lisa Rose),(0.92447, Gene Seymour),(0.89341, Michael Phillips),(0.66285, Claudia Puig),(0.38125, Mick LaSalle),(0.00000, Jack Matthews),(-1.00000, Toby)
if (!prefs[p1].movi[x].rating && !prefs[p2].movi[next].rating);
else if (strcmp(prefs[p1].movi[x].mName, prefs[p2].movi[next].mName) == 0) {
to:到:
if (
(prefs[p1].movi[x].rating || prefs[p2].movi[next].rating) &&
!strcmp(prefs[p1].movi[x].mName, prefs[p2].movi[next].mName)
) {
If you introduce a couple of vanity variables it could be written a more compactly.如果您引入几个虚荣变量,它可以写得更紧凑。
float
with double
and fix the sort function:将float
替换为double
并修复排序 function:int cmpFxn (const void * a, const void * b) {
double a2 = *(double *) a;
double b2 = *(double *) b;
if(a2 < b2) return -1;
if(a2 > b2) return 1;
return 0;
}
double scores[8];
valgrind 报告在 topMatches 中使用未初始化的数据,特别double scores[8];
. . You only iterate over num
which is 7
, and you don't set scores[i] for the entry that corresponds to person1 so I suggest you do:您只迭代num
,即7
,并且您没有为对应于 person1 的条目设置 scores[i] 所以我建议您这样做: double scores[num];
memset(scores, 0, sizeof(scores));
sizeof a / sizeof *a
if you need the size of an array (be careful arrays degrade to pointers when passed as arguments). (不固定)检查你的代码是否有神奇的值,比如 7 和 20。如果你需要数组的大小,使用常量,传入一个参数或sizeof a / sizeof *a
(小心 arrays 在作为参数传递时降级为指针) .At least these issues:至少这些问题:
Wrong compare function错误比较 function
qsort()
is called with an array of float
and cmpFxn
, yet cmpFxn()
compares int
.使用float
和cmpFxn
数组调用qsort()
,但cmpFxn()
比较int
。 *1 *1
Need to cast to float
.需要投射到float
。 *2 *2
// return (*(int*)a - *(int*)b )
return (*(float*)a > *(float*)b ) - (*(float*)a < *(float*)b );
No not use return (*(float*)a - *(float*)b )
as the float
difference may overflow int
range or truncate to 0.不要不使用return (*(float*)a - *(float*)b )
因为float
差异可能会溢出int
范围或截断为 0。
Code risks sqrt(some_negative)
代码风险sqrt(some_negative)
Watch out for slight floating point artifacts that result in a negative that mathematically should never be less than 0.注意轻微的浮点伪影,这些伪影会导致数学上永远不应小于 0 的负数。
// den=sqrt((sumSq1-pow(X,2)/nElements)*(sumSq2-pow(Y,2)/nElements));
t = (sumSq1-pow(X,2)/nElements)*(sumSq2-pow(Y,2)/nElements);
den = t >= 0.0 ? sqrt(t) : 0;
float
vs. double
float
与double
Code is casual about mixing float
and double
objects and functions.代码随意混合float
和double
对象和函数。 Suggest double
only.建议只double
。
For debug purposes, easy enough to use #define float double
to temporarily do this.出于调试目的,很容易使用#define float double
来临时执行此操作。
*1 *1
cmpFxn()
is also a weak compare function for int
too as it risks int
overflow. cmpFxn()
也是int
的弱比较 function,因为它有int
溢出的风险。
// return ( *(int*)a - *(int*)b );
return (*(int*)a > *(int*)b ) - (*(int*)a < *(int*)b );
*2 *2
If not-a-numbers are involved, the compare is more complicated.如果涉及非数字,则比较更加复杂。 Let us assume, for now, that is not the case.让我们暂时假设情况并非如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.