Flavien
(Getting the hang of it)
2016-02-29 05:56 PM
Multiplication bug on non-English user locales

This is a creepy one, I've managed to reproduce with just this one-liner:

 Code:
? "0.000001024 * 48845580 = " 0.000001024 * 48845580 " (Expected result: 50.01787392)"


I've tested with many versions of KiXtart (from 4.02 to 4.66), on Windows 7 and 10: result is always 0 when the user language is not in English. The system language has no impact.

Workaround:
Use a division instead of a multiplication, for example: 48845580 / 976562.5


AllenAdministrator
(KiX Supporter)
2016-02-29 06:17 PM
Re: Multiplication bug on non-English user locales

What happens when you simply do the math and set it to a variable?

 Code:
$value=0.000001024 * 48845580
? "0.000001024 * 48845580 = " + $value +  " (Expected result: 50.01787392)"


and it would probably help to keep both numbers as double for the math to be consistent, ie 48845580.0


Glenn BarnasAdministrator
(KiX Supporter)
2016-02-29 06:42 PM
Re: Multiplication bug on non-English user locales

Well, my guess would be that many non-English environments use "," as a decimal point, not the period (.), and that the format is thus invalid. Indeed, when I replace the "." with a "," on my US-English workstation, I get zero as a result, followed by an error (since the comma isn't at all valid here).
 Code:
"0.000001024 * 48845580 = " 0.000001024 * 48845580 " (Expected result: 50.01787392)" ?
"0,000001024 * 48845580 = " 0,000001024 * 48845580 " (Expected result: 50.01787392)" ?
You'll have to try this on a non-English system. I tried on a W-7 system and could not get it to work using the "," but it did not fail using the "." either when set to Germany for both Language and Location.

Glenn


Flavien
(Getting the hang of it)
2016-02-29 07:13 PM
Re: Multiplication bug on non-English user locales

This is on a French locale:

 Code:
? "cdbl(1024 / 1000000000) * 48845580: " cdbl(1024 / 1000000000) * 48845580
? "cdbl(1024) / 1000000000 * 48845580: " cdbl(1024) / 1000000000 * 48845580
? "cdbl(0.000001024) * 48845580: " cdbl(0.000001024) * 48845580
? "0,000001024 * 48845580: " 0,000001024 * 48845580


Result:

 Code:
cdbl(1024 / 1000000000) * 48845580: 0
cdbl(1024) / 1000000000 * 48845580: 50,01787392
cdbl(0.000001024) * 48845580: 0
0,000001024 * 48845580: 0
ERROR : unexpected command!
Script: C:\Users\...\test.kix
Line  : 4


Clearly a bug in KiXtart.

Another workaround is to use cdbl() instead of x.0, and don't do calculation in cdbl().


LonkeroAdministrator
(KiX Master Guru)
2016-04-13 04:09 AM
Re: Multiplication bug on non-English user locales

you can't use comma outside quotation marks since it is a KiXtart separator.

I just tried your original one-liner with 4.66 and with Finnish and it worked beautifully.


Flavien
(Getting the hang of it)
2016-04-13 08:30 AM
Re: Multiplication bug on non-English user locales

This problem arises when the user selects a digit separator that is not a dot (.), like a comma (,) as seen in French, Swiss and other European locales.

To make my scripts bullet proof for these non-dot separators, I had to:

1. Convert to double by using divisions, e.g. 6.1 = 61/10:
 Code:
$windows_7_plus = cdbl(61) / 10
if cdbl(readvalue("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion")) >= $windows_7_plus
	;Windows 7 and 2008R2+.
endif


2. Use this function to convert a double to a string:
 Code:
function cdbl_to_string($cdbl, optional $decimals)
	;Convert and round a double-precision floating-point value (cdbl) to a string with a dot (.) as numerical separator.
	dim $index, $digit, $string, $decimal_set
	$cdbl = round($cdbl, $decimals)
	if $decimals > 0
		$decimal_set = 0
	else
		$decimal_set = 1
	endif
	$string = cstr($cdbl)
	;Replace any kind of separator (e.g. comma) with a dot (.).
	for $index = len($string) to 1 step -1
		dim $digit_ascii, $new_digit
		$digit = substr($string, $index, 1)
		$digit_ascii  = asc(substr($string, $index, 1))
		if ($digit_ascii < 48 or $digit_ascii > 57)
			if $decimal_set = 0
				$new_digit = "."
				$decimal_set = 1
			endif
		else
			$new_digit = $digit
		endif
		$cdbl_to_string = $new_digit + $cdbl_to_string
	next
	if $decimals > 0 and $decimal_set = 0
		$cdbl_to_string = $cdbl_to_string + ".0"
	endif
endfunction