diff --git a/src/operators.c b/src/operators.c
index 247669a40e5f9dcf64eef1fc0359e97d488b1a5a..5125e87ca16b41198149296fe9818069c4740655 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -6,7 +6,7 @@
 /**/
 #include "global.h"
 #include <math.h>
-RCSID("$Id: operators.c,v 1.108 2000/10/03 13:42:44 grubba Exp $");
+RCSID("$Id: operators.c,v 1.109 2000/10/14 22:17:58 grubba Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -1648,35 +1648,40 @@ PMOD_EXPORT void o_multiply(void)
 
     case TWO_TYPES(T_ARRAY, T_FLOAT):
       {
+	struct array *src;
 	struct array *ret;
 	struct svalue *pos;
-	INT_TYPE e, asize, extra;
+	ptrdiff_t asize, delta;
 	if(sp[-1].u.float_number < 0)
 	  SIMPLE_BAD_ARG_ERROR("`*", 2, "float(0..)");
-	/* Think of that big floats are not always the same as a 
-	   converted big int! That's why we have to make this in
-	   two steps. */
-	extra=(int)(((double)sp[-2].u.array->size * 
-		     (sp[-1].u.float_number 
-		      - (double)(int)sp[-1].u.float_number))+
-		    0.5);
-        asize=((int)(double)(sp[-2].u.array->size * (int)sp[-1].u.float_number))+
-	  extra;
-	ret=allocate_array(asize);
-	pos=ret->item;
-	for(e=0;e<((int)sp[-1].u.float_number);e++,pos+=sp[-2].u.array->size)
+
+	src = sp[-2].u.array;
+	delta = src->size;
+	asize = (ptrdiff_t)floor(delta * sp[-1].u.float_number + 0.5);
+	ret = allocate_array(asize);
+	pos = ret->item;
+	if (asize >= delta) {
 	  assign_svalues_no_free(pos,
-				 sp[-2].u.array->item,
-				 sp[-2].u.array->size,
-				 sp[-2].u.array->type_field);
-	/* copy the last part of the array */
-	if (extra)
+				 src->item,
+				 delta,
+				 src->type_field);
+	  pos += delta;
+	  asize -= delta;
+	  while (asize >= delta) {
+	    assign_svalues_no_free(pos, ret->item, delta, ret->type_field);
+	    pos += delta;
+	    asize -= delta;
+	    delta <<= 1;
+	  }
+	  if (asize) {
+	    assign_svalues_no_free(pos, ret->item, asize, ret->type_field);
+	  }
+	} else if (asize) {
 	  assign_svalues_no_free(pos,
-				 sp[-2].u.array->item,
-				 extra,
-				 sp[-2].u.array->type_field);
-
-	ret->type_field=sp[-2].u.array->type_field;
+				 src->item,
+				 asize,
+				 src->type_field);
+	}
 	pop_n_elems(2);
 	push_array(ret);
 	return;
@@ -1684,32 +1689,35 @@ PMOD_EXPORT void o_multiply(void)
 
     case TWO_TYPES(T_STRING, T_FLOAT):
       {
+	struct pike_string *src;
 	struct pike_string *ret;
 	char *pos;
-	INT_TYPE e, asize, extra;
-	ptrdiff_t len;
+	ptrdiff_t len, delta;
+
 	if(sp[-1].u.float_number < 0)
 	  SIMPLE_BAD_ARG_ERROR("`*", 2, "float(0..)");
-	/* Think of that big floats are not always the same as a 
-	   converted big int! That's why we have to make this in
-	   two steps. */
-	extra=(int)(((double)sp[-2].u.string->len * 
-		     (sp[-1].u.float_number 
-		      - (double)(int)sp[-1].u.float_number))+
-		    0.5);
-        asize=((int)(double)(sp[-2].u.string->len * (int)sp[-1].u.float_number))+
-	  extra;
-	ret=begin_wide_shared_string(asize,
-				     sp[-2].u.string->size_shift);
-	pos=ret->str;
-	len=sp[-2].u.string->len << sp[-2].u.string->size_shift;
-	for(e=0;e<((int)sp[-1].u.float_number);e++,pos+=len)
-	  MEMCPY(pos,sp[-2].u.string->str,len);
-	/* copy the last part of the string */
-	if (extra)
-	{
-	  extra=extra << sp[-2].u.string->size_shift;
-	  MEMCPY(pos,sp[-2].u.string->str,extra);
+	src = sp[-2].u.string;
+	len = (ptrdiff_t)floor(src->len * sp[-1].u.float_number + 0.5);
+	ret = begin_wide_shared_string(len, src->size_shift);
+	len <<= src->size_shift;
+	delta = src->len << src->size_shift;
+	pos = ret->str;
+
+	if (len >= delta) {
+	  MEMCPY(pos, src->str, delta);
+	  pos += delta;
+	  len -= delta;
+	  while (len >= delta) {
+	    MEMCPY(pos, ret->str, delta);
+	    pos += delta;
+	    len -= delta;
+	    delta <<= 1;
+	  }
+	  if (len) {
+	    MEMCPY(pos, ret->str, len);
+	  }
+	} else if (len) {
+	  MEMCPY(pos, src->str, len);
 	}
 	pop_n_elems(2);
 	push_string(low_end_shared_string(ret));