Commit d68a5fd5 authored by Jukka-Pekka Iivonen's avatar Jukka-Pekka Iivonen Committed by jpekka

Implemented t-Test and z-Test tools.

1999-07-06  Jukka-Pekka Iivonen  <iivonen@iki.fi>

	* src/analysis-tools.c, src/dialog-analysis-tools.c,
 	src/dialogs.h: Implemented t-Test and z-Test tools.
parent 173914b0
......@@ -11,6 +11,9 @@ Jukka:
- Implemented Correlation and Covariance tools
- Implemented Descriptive Statistics Tool
- Implemented Sampling Tool
- Implemented t-Test Tools (paired, assuming equal variance and
assuming unequal variance)
- Implemented z-Test Tool
* Added the following functions:
- FORECAST() and INTERCEPT().
* And fixed these functions:
......
1999-07-06 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/analysis-tools.c, src/dialog-analysis-tools.c,
src/dialogs.h: Implemented t-Test and z-Test tools.
1999-07-05 Miguel de Icaza <miguel@gnu.org>
* src/about.c (dialog_about): Added link to IGS web site.
......
1999-07-06 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/analysis-tools.c, src/dialog-analysis-tools.c,
src/dialogs.h: Implemented t-Test and z-Test tools.
1999-07-05 Miguel de Icaza <miguel@gnu.org>
* src/about.c (dialog_about): Added link to IGS web site.
......
1999-07-06 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/analysis-tools.c, src/dialog-analysis-tools.c,
src/dialogs.h: Implemented t-Test and z-Test tools.
1999-07-05 Miguel de Icaza <miguel@gnu.org>
* src/about.c (dialog_about): Added link to IGS web site.
......
1999-07-06 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/analysis-tools.c, src/dialog-analysis-tools.c,
src/dialogs.h: Implemented t-Test and z-Test tools.
1999-07-05 Miguel de Icaza <miguel@gnu.org>
* src/about.c (dialog_about): Added link to IGS web site.
......
......@@ -916,3 +916,465 @@ int sampling_tool (Workbook *wb, Sheet *sheet, Range *input_range,
return 0;
}
/************* z-Test: Two Sample for Means ******************************
*
* The results are given in a table which can be printed out in a new
* sheet, in a new workbook, or simply into an existing sheet.
*
* TODO: a new workbook output and output to an existing sheet
*
**/
int ztest_tool (Workbook *wb, Sheet *sheet, Range *input_range1,
Range *input_range2, float_t mean_diff, float_t known_var1,
float_t known_var2, float_t alpha,
data_analysis_output_t *dao)
{
data_set_t set_one, set_two;
float_t mean1, mean2, var1, var2, z, p;
char buf[256];
if (dao->type == NewSheetOutput) {
dao->sheet = sheet_new(wb, "z-Test");
dao->start_col = dao->start_row = 0;
workbook_attach_sheet(wb, dao->sheet);
}
get_data(sheet, input_range1, &set_one);
get_data(sheet, input_range2, &set_two);
set_cell (dao, 0, 0, "");
set_cell (dao, 1, 0, "Variable 1");
set_cell (dao, 2, 0, "Variable 2");
set_cell (dao, 0, 1, "Mean");
set_cell (dao, 0, 2, "Known Variance");
set_cell (dao, 0, 3, "Observations");
set_cell (dao, 0, 4, "Hypothesized Mean Difference");
set_cell (dao, 0, 5, "z");
set_cell (dao, 0, 6, "P(Z<=z) one-tail");
set_cell (dao, 0, 7, "z Critical one-tail");
set_cell (dao, 0, 8, "P(Z<=z) two-tail");
set_cell (dao, 0, 9, "z Critical two-tail");
mean1 = set_one.sum / set_one.n;
mean2 = set_two.sum / set_two.n;
var1 = (set_one.sqrsum - set_one.sum2/set_one.n) / (set_one.n - 1);
var2 = (set_two.sqrsum - set_two.sum2/set_two.n) / (set_two.n - 1);
z = (mean1 - mean2 - mean_diff) /
sqrt(known_var1/set_one.n + known_var2/set_two.n);
p = 1 - pnorm(z, 0, 1);
/* Mean */
sprintf(buf, "%f", mean1);
set_cell(dao, 1, 1, buf);
sprintf(buf, "%f", mean2);
set_cell(dao, 2, 1, buf);
/* Known Variance */
sprintf(buf, "%f", known_var1);
set_cell(dao, 1, 2, buf);
sprintf(buf, "%f", known_var2);
set_cell(dao, 2, 2, buf);
/* Observations */
sprintf(buf, "%d", set_one.n);
set_cell(dao, 1, 3, buf);
sprintf(buf, "%d", set_two.n);
set_cell(dao, 2, 3, buf);
/* Hypothesized Mean Difference */
sprintf(buf, "%f", mean_diff);
set_cell(dao, 1, 4, buf);
/* z */
sprintf(buf, "%f", z);
set_cell(dao, 1, 5, buf);
/* P(Z<=z) one-tail */
sprintf(buf, "%f", p);
set_cell(dao, 1, 6, buf);
/* z Critical one-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 7, buf);
/* P(Z<=z) two-tail */
sprintf(buf, "%f", 2*p);
set_cell(dao, 1, 8, buf);
/* z Critical two-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 9, buf);
free_data_set (&set_one);
free_data_set (&set_two);
return 0;
}
/************* t-Test Tools ********************************************
*
* The t-Test tool set consists of three kinds of tests to test the
* mean of two variables. The tests are: Student's t-test for paired
* sample, Student's t-test for two samples assuming equal variance
* and the same test assuming unequal variance. The results are given
* in a table which can be printed out in a new sheet, in a new
* workbook, or simply into an existing sheet.
*
* TODO: a new workbook output and output to an existing sheet
*
**/
/* t-Test: Paired Two Sample for Means.
*/
int
ttest_paired_tool (Workbook *wb, Sheet *sheet, Range *input_range1,
Range *input_range2, float_t mean_diff, float_t alpha,
data_analysis_output_t *dao)
{
data_set_t set_one, set_two;
GSList *current_one, *current_two;
float_t mean1, mean2, pearson, var1, var2, t, p, df, sum_xy, sum;
float_t dx, dm, M, Q, N, s;
char buf[256];
get_data(sheet, input_range1, &set_one);
get_data(sheet, input_range2, &set_two);
if (set_one.n != set_two.n) {
free_data_set(&set_one);
free_data_set(&set_two);
return 1;
}
if (dao->type == NewSheetOutput) {
dao->sheet = sheet_new(wb, "t-Test");
dao->start_col = dao->start_row = 0;
workbook_attach_sheet(wb, dao->sheet);
}
set_cell (dao, 0, 0, "");
set_cell (dao, 1, 0, "Variable 1");
set_cell (dao, 2, 0, "Variable 2");
set_cell (dao, 0, 1, "Mean");
set_cell (dao, 0, 2, "Variance");
set_cell (dao, 0, 3, "Observations");
set_cell (dao, 0, 4, "Pearson Correlation");
set_cell (dao, 0, 5, "Hypothesized Mean Difference");
set_cell (dao, 0, 6, "df");
set_cell (dao, 0, 7, "t Stat");
set_cell (dao, 0, 8, "P(T<=t) one-tail");
set_cell (dao, 0, 9, "t Critical one-tail");
set_cell (dao, 0, 10, "P(T<=t) two-tail");
set_cell (dao, 0, 11, "t Critical two-tail");
current_one = set_one.array;
current_two = set_two.array;
sum = sum_xy = 0;
dx = dm = M = Q = N = 0;
while (current_one != NULL && current_two != NULL) {
float_t x, y, d;
x = *((float_t *) current_one->data);
y = *((float_t *) current_two->data);
sum_xy += x*y;
d = x-y;
sum += d;
dx = d - M;
dm = dx / (N + 1);
M += dm;
Q += N * dx * dm;
N++;
current_one = current_one->next;
current_two = current_two->next;
}
mean1 = set_one.sum / set_one.n;
mean2 = set_two.sum / set_two.n;
var1 = (set_one.sqrsum - set_one.sum2/set_one.n) / (set_one.n - 1);
var2 = (set_two.sqrsum - set_two.sum2/set_two.n) / (set_two.n - 1);
df = set_one.n - 1;
pearson = ((set_one.n*sum_xy - set_one.sum*set_two.sum) /
sqrt((set_one.n*set_one.sqrsum - set_one.sum2) *
(set_one.n*set_two.sqrsum - set_two.sum2)));
s = sqrt(Q / (N - 1));
t = (sum/set_one.n - mean_diff)/(s/sqrt(set_one.n));
p = 1.0 - pt(fabs(t), df);
/* Mean */
sprintf(buf, "%f", mean1);
set_cell(dao, 1, 1, buf);
sprintf(buf, "%f", mean2);
set_cell(dao, 2, 1, buf);
/* Variance */
sprintf(buf, "%f", var1);
set_cell(dao, 1, 2, buf);
sprintf(buf, "%f", var2);
set_cell(dao, 2, 2, buf);
/* Observations */
sprintf(buf, "%d", set_one.n);
set_cell(dao, 1, 3, buf);
sprintf(buf, "%d", set_two.n);
set_cell(dao, 2, 3, buf);
/* Pearson Correlation */
sprintf(buf, "%f", pearson);
set_cell(dao, 1, 4, buf);
/* Hypothesized Mean Difference */
sprintf(buf, "%f", mean_diff);
set_cell(dao, 1, 5, buf);
/* df */
sprintf(buf, "%f", df);
set_cell(dao, 1, 6, buf);
/* t */
sprintf(buf, "%f", t);
set_cell(dao, 1, 7, buf);
/* P(T<=t) one-tail */
sprintf(buf, "%f", p);
set_cell(dao, 1, 8, buf);
/* t Critical two-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 9, buf);
/* P(T<=t) two-tail */
sprintf(buf, "%f", 2*p);
set_cell(dao, 1, 10, buf);
/* t Critical two-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 11, buf);
free_data_set(&set_one);
free_data_set(&set_two);
return 0;
}
/* t-Test: Two-Sample Assuming Equal Variances.
*/
int
ttest_eq_var_tool (Workbook *wb, Sheet *sheet, Range *input_range1,
Range *input_range2, float_t mean_diff, float_t alpha,
data_analysis_output_t *dao)
{
data_set_t set_one, set_two;
float_t mean1, mean2, var, var1, var2, t, p, df;
char buf[256];
if (dao->type == NewSheetOutput) {
dao->sheet = sheet_new(wb, "t-Test");
dao->start_col = dao->start_row = 0;
workbook_attach_sheet(wb, dao->sheet);
}
get_data(sheet, input_range1, &set_one);
get_data(sheet, input_range2, &set_two);
set_cell (dao, 0, 0, "");
set_cell (dao, 1, 0, "Variable 1");
set_cell (dao, 2, 0, "Variable 2");
set_cell (dao, 0, 1, "Mean");
set_cell (dao, 0, 2, "Variance");
set_cell (dao, 0, 3, "Observations");
set_cell (dao, 0, 4, "Pooled Variance");
set_cell (dao, 0, 5, "Hypothesized Mean Difference");
set_cell (dao, 0, 6, "df");
set_cell (dao, 0, 7, "t Stat");
set_cell (dao, 0, 8, "P(T<=t) one-tail");
set_cell (dao, 0, 9, "t Critical one-tail");
set_cell (dao, 0, 10, "P(T<=t) two-tail");
set_cell (dao, 0, 11, "t Critical two-tail");
mean1 = set_one.sum / set_one.n;
mean2 = set_two.sum / set_two.n;
var1 = (set_one.sqrsum - set_one.sum2/set_one.n) / (set_one.n - 1);
var2 = (set_two.sqrsum - set_two.sum2/set_two.n) / (set_two.n - 1);
var = (set_one.sqrsum+set_two.sqrsum - (set_one.sum+set_two.sum)*
(set_one.sum+set_two.sum)/(set_one.n+set_two.n)) /
(set_one.n+set_two.n-1); /* TODO: Correct??? */
df = set_one.n + set_two.n - 2;
t = fabs(mean1 - mean2 - mean_diff) /
sqrt(var1/set_one.n + var2/set_two.n);
p = 1.0 - pt(t, df);
/* Mean */
sprintf(buf, "%f", mean1);
set_cell(dao, 1, 1, buf);
sprintf(buf, "%f", mean2);
set_cell(dao, 2, 1, buf);
/* Variance */
sprintf(buf, "%f", var1);
set_cell(dao, 1, 2, buf);
sprintf(buf, "%f", var2);
set_cell(dao, 2, 2, buf);
/* Observations */
sprintf(buf, "%d", set_one.n);
set_cell(dao, 1, 3, buf);
sprintf(buf, "%d", set_two.n);
set_cell(dao, 2, 3, buf);
/* Pooled Variance */
sprintf(buf, "%f", var);
set_cell(dao, 1, 4, buf);
/* Hypothesized Mean Difference */
sprintf(buf, "%f", mean_diff);
set_cell(dao, 1, 5, buf);
/* df */
sprintf(buf, "%f", df);
set_cell(dao, 1, 6, buf);
/* t */
sprintf(buf, "%f", t);
set_cell(dao, 1, 7, buf);
/* P(T<=t) one-tail */
sprintf(buf, "%f", p);
set_cell(dao, 1, 8, buf);
/* t Critical two-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 9, buf);
/* P(T<=t) two-tail */
sprintf(buf, "%f", 2*p);
set_cell(dao, 1, 10, buf);
/* t Critical two-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 11, buf);
free_data_set(&set_one);
free_data_set(&set_two);
return 0;
}
/* t-Test: Two-Sample Assuming Unequal Variances.
*/
int
ttest_neq_var_tool (Workbook *wb, Sheet *sheet, Range *input_range1,
Range *input_range2, float_t mean_diff, float_t alpha,
data_analysis_output_t *dao)
{
data_set_t set_one, set_two;
float_t mean1, mean2, var1, var2, t, p, df, c;
char buf[256];
if (dao->type == NewSheetOutput) {
dao->sheet = sheet_new(wb, "t-Test");
dao->start_col = dao->start_row = 0;
workbook_attach_sheet(wb, dao->sheet);
}
get_data(sheet, input_range1, &set_one);
get_data(sheet, input_range2, &set_two);
set_cell (dao, 0, 0, "");
set_cell (dao, 1, 0, "Variable 1");
set_cell (dao, 2, 0, "Variable 2");
set_cell (dao, 0, 1, "Mean");
set_cell (dao, 0, 2, "Variance");
set_cell (dao, 0, 3, "Observations");
set_cell (dao, 0, 4, "Hypothesized Mean Difference");
set_cell (dao, 0, 5, "df");
set_cell (dao, 0, 6, "t Stat");
set_cell (dao, 0, 7, "P(T<=t) one-tail");
set_cell (dao, 0, 8, "t Critical one-tail");
set_cell (dao, 0, 9, "P(T<=t) two-tail");
set_cell (dao, 0, 10, "t Critical two-tail");
mean1 = set_one.sum / set_one.n;
mean2 = set_two.sum / set_two.n;
var1 = (set_one.sqrsum - set_one.sum2/set_one.n) / (set_one.n - 1);
var2 = (set_two.sqrsum - set_two.sum2/set_two.n) / (set_two.n - 1);
c = (var1/set_one.n) / (var1/set_one.n+var2/set_two.n);
df = 1.0 / ((c*c) / (set_one.n-1.0) + ((1-c)*(1-c)) / (set_two.n-1.0));
t = fabs(mean1 - mean2 - mean_diff) /
sqrt(var1/set_one.n + var2/set_two.n);
p = 1.0 - pt(t, df);
/* Mean */
sprintf(buf, "%f", mean1);
set_cell(dao, 1, 1, buf);
sprintf(buf, "%f", mean2);
set_cell(dao, 2, 1, buf);
/* Variance */
sprintf(buf, "%f", var1);
set_cell(dao, 1, 2, buf);
sprintf(buf, "%f", var2);
set_cell(dao, 2, 2, buf);
/* Observations */
sprintf(buf, "%d", set_one.n);
set_cell(dao, 1, 3, buf);
sprintf(buf, "%d", set_two.n);
set_cell(dao, 2, 3, buf);
/* Hypothesized Mean Difference */
sprintf(buf, "%f", mean_diff);
set_cell(dao, 1, 4, buf);
/* df */
sprintf(buf, "%f", df);
set_cell(dao, 1, 5, buf);
/* t */
sprintf(buf, "%f", t);
set_cell(dao, 1, 6, buf);
/* P(T<=t) one-tail */
sprintf(buf, "%f", p);
set_cell(dao, 1, 7, buf);
/* t Critical two-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 8, buf);
/* P(T<=t) two-tail */
sprintf(buf, "%f", 2*p);
set_cell(dao, 1, 9, buf);
/* t Critical two-tail */
sprintf(buf, "%f", 0.0); /* TODO */
set_cell(dao, 1, 10, buf);
free_data_set(&set_one);
free_data_set(&set_two);
return 0;
}
......@@ -22,6 +22,12 @@ dummy_fun (Workbook *wb, Sheet *sheet)
/* Nothing. */
}
static void dialog_ztest_tool(Workbook *wb, Sheet *sheet);
static void dialog_ttest_paired_tool(Workbook *wb, Sheet *sheet);
static void dialog_ttest_eq_tool(Workbook *wb, Sheet *sheet);
static void dialog_ttest_neq_tool(Workbook *wb, Sheet *sheet);
typedef void (*tool_fun_ptr_t)(Workbook *wb, Sheet *sheet);
typedef struct {
......@@ -47,6 +53,13 @@ tool_list_t tools[] = {
{ { "Covariance", NULL }, dummy_fun },
{ { "Descriptive Statistics", NULL }, dummy_fun },
{ { "Sampling", NULL }, dummy_fun },
{ { "t-Test: Paired Two Sample for Means", NULL },
dialog_ttest_paired_tool },
{ { "t-Test: Two-Sample Assuming Equal Variances", NULL },
dialog_ttest_eq_tool },
{ { "t-Test: Two-Sample Assuming Unequal Variances", NULL },
dialog_ttest_neq_tool },
{ { "z-Test: Two Sample for Means", NULL }, dialog_ztest_tool },
{ { NULL, NULL }, NULL }
};
......@@ -327,6 +340,435 @@ tool_dialog_loop:
gnome_dialog_close (GNOME_DIALOG (dialog[ti]));
}
static GtkWidget *
hbox_pack_label_and_entry(char *str, char *default_str,
int entry_len, GtkWidget *vbox)
{
GtkWidget *box, *label, *entry;
box = gtk_hbox_new (FALSE, 0);
entry = gtk_entry_new_with_max_length (entry_len);
label = gtk_label_new (str);
gtk_entry_set_text (GTK_ENTRY (entry), default_str);
gtk_box_pack_start_defaults (GTK_BOX (box), label);
gtk_box_pack_start_defaults (GTK_BOX (box), entry);
gtk_box_pack_start_defaults (GTK_BOX (vbox), box);
return entry;
}
static GtkWidget *
new_dialog(char *name, GtkWidget *win)
{
GtkWidget *dialog;
dialog = gnome_dialog_new (_(name),
_("OK"),
GNOME_STOCK_BUTTON_CANCEL,
NULL);
gnome_dialog_close_hides (GNOME_DIALOG (dialog), TRUE);
gnome_dialog_set_parent (GNOME_DIALOG (dialog), GTK_WINDOW (win));
return dialog;
}
static void
dialog_ztest_tool(Workbook *wb, Sheet *sheet)
{
static GtkWidget *dialog, *box;
static GtkWidget *range1_entry, *range2_entry;
static GtkWidget *known_var1_entry, *known_var2_entry;
static GtkWidget *mean_diff_entry, *alpha_entry;
data_analysis_output_t dao;
float_t mean_diff, alpha, var1, var2;
char *text;
int selection;
static Range range_input1, range_input2;
int i=0, size;
if (!dialog) {
dialog = new_dialog("z-Test: Two Sample for Means",
wb->toplevel);
box = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start_defaults (GTK_BOX (GNOME_DIALOG
(dialog)->vbox), box);
range1_entry = hbox_pack_label_and_entry
("Variable 1 Range:", "", 20, box);
range2_entry = hbox_pack_label_and_entry
("Variable 2 Range:", "", 20, box);
mean_diff_entry = hbox_pack_label_and_entry
("Hypothesized Mean Difference:", "0", 20, box);
known_var1_entry = hbox_pack_label_and_entry
("Variable 1 Variance (known):", "", 20, box);
known_var2_entry = hbox_pack_label_and_entry
("Variable 2 Variance (known):", "", 20, box);
alpha_entry = hbox_pack_label_and_entry("Alpha:", "0.95",
20, box);
gtk_widget_show_all (dialog);
} else
gtk_widget_show_all (dialog);
gtk_widget_grab_focus (range1_entry);
ztest_dialog_loop:
selection = gnome_dialog_run (GNOME_DIALOG (dialog));
if (selection == 1) {
gnome_dialog_close (GNOME_DIALOG (dialog));
return;
}
text = gtk_entry_get_text (GTK_ENTRY (range1_entry));
if (!parse_range (text, &range_input1.start_col,
&range_input1.start_row,
&range_input1.end_col,
&range_input1.end_row)) {
gnumeric_notice (wb, GNOME_MESSAGE_BOX_ERROR,
_("You should introduce a valid cell range "
"in 'Variable 1:'"));
gtk_widget_grab_focus (range1_entry);
gtk_entry_set_position(GTK_ENTRY (range1_entry), 0);
gtk_entry_select_region(GTK_ENTRY (range1_entry), 0,
GTK_ENTRY(range1_entry)->text_length);
goto ztest_dialog_loop;
}
text = gtk_entry_get_text (GTK_ENTRY (range2_entry));
if (!parse_range (text, &range_input2.start_col,
&range_input2.start_row,
&range_input2.end_col,
&range_input2.end_row)) {
gnumeric_notice (wb, GNOME_MESSAGE_BOX_ERROR,
_("You should introduce a valid cell range "
"in 'Variable 2:'"));
gtk_widget_grab_focus (range2_entry);
gtk_entry_set_position(GTK_ENTRY (range2_entry), 0);
gtk_entry_select_region(GTK_ENTRY (range2_entry), 0,
GTK_ENTRY(range2_entry)->text_length);
goto ztest_dialog_loop;
}
text = gtk_entry_get_text (GTK_ENTRY (mean_diff_entry));
mean_diff = atof(text);
text = gtk_entry_get_text (GTK_ENTRY (alpha_entry));
alpha = atof(text);
text = gtk_entry_get_text (GTK_ENTRY (known_var1_entry));
var1 = atof(text);
text = gtk_entry_get_text (GTK_ENTRY (known_var2_entry));
var2 = atof(text);
/* TODO: radio buttos for outputs */
dao.type = NewSheetOutput;
ztest_tool (wb, sheet, &range_input1, &range_input2, mean_diff,
var1, var2, alpha, &dao);
workbook_focus_sheet(sheet);
gnome_dialog_close (GNOME_DIALOG (dialog));
}
static void
dialog_ttest_paired_tool(Workbook *wb, Sheet *sheet)
{
static GtkWidget *dialog, *box;
static GtkWidget *range1_entry, *range2_entry;
static GtkWidget *mean_diff_entry, *alpha_entry;
data_analysis_output_t dao;
float_t mean_diff, alpha;
char *text;
int selection;
static Range range_input1, range_input2;
int i=0, size;
if (!dialog) {
dialog = new_dialog("t-Test: Paired Two Sample for Means",
wb->toplevel);
box = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start_defaults (GTK_BOX (GNOME_DIALOG
(dialog)->vbox), box);
range1_entry = hbox_pack_label_and_entry
("Variable 1 Range:", "", 20, box);
range2_entry = hbox_pack_label_and_entry
("Variable 2 Range:", "", 20, box);
mean_diff_entry = hbox_pack_label_and_entry
("Hypothesized Mean Difference:", "0", 20, box);