как работает команда tert для действительных чисел

Мне очень нравится команда tert() в DigitalMicrograph, но я чего-то в ней не понимаю. Рассмотрим тестовый сценарий:

image test:= realimage("",4,100,1);
number value1 = 1;
number value2 = 0.1;
if(value2==0.1) result("\nvalue2 really equals 0.1");
test.setPixel(5,0,value1);
test.setPixel(10,0,value2);

image mask = imageclone(test);
mask = 0;
mask = tert(test==value1,1,mask);
mask = tert(test==value2,1,mask);
mask.showimage()

Скрипт находит пиксель, в котором массив «тест» равен значению1, но не находит его для значения2. Похоже, что команда tert понимает условие (test==value) только тогда, когда «значение» является целым числом. В противном случае считается, что эквивалентность НЕ ТОЧНА. Это странно, потому что число Value2 было неявно (я предполагаю) определено как действительное число, а затем присвоено реальному массиву. Как DigitalMicrograph определяет, является ли значение целым/действительным/двойным?


person pavel    schedule 17.05.2016    source источник
comment
Небольшой комментарий по синтаксису: X = tert(A,B,C) также может быть записано как X = A ? B : C, что иногда легче читать (и также работает со строками).   -  person BmyGuest    schedule 21.05.2016


Ответы (1)


То, что вы здесь заметили, является типичной проблемой при сравнении значений с плавающей запятой без небольшого, но ненулевого допуска для ограниченной точности представлений с плавающей запятой. В вашем конкретном тестовом сценарии проблема возникает из-за того, что числовые значения в DMS всегда имеют двойную точность, поэтому вы эффективно сравниваете 4-байтовые значения с плавающей запятой в тестовом изображении с 8-байтовыми значениями с плавающей запятой, хранящимися в объектах Number. Ваш сценарий правильно найдет оба значения, если вы измените первую строку, чтобы выделить тестовому изображению 8-байтовые значения с плавающей запятой, как показано ниже:

image test:= realimage("",8,100,1);

С другой стороны, более надежным решением является использование небольшого ненулевого допуска при сравнении значений с плавающей запятой для «равенства». В частности, если вы измените тестовые строки вашего скрипта, которые вызывают функцию tert, следующим образом, то он также правильно найдет оба значения:

mask = tert(Abs((test-value1)/value1)<1e-7,1,mask);
mask = tert(Abs((test-value2)/value2)<1e-7,1,mask);
person Mike Kundmann    schedule 18.05.2016