2015-09-04 3 views
-1

Таким образом, в C++ я могу сделать что-то вроде:DWORD деление Delphi/C++

DWORD count; 

count = 3/1.699999; 

cout << count; 

, которая приведет:

Delphi однако сетует Кардинала и Extended рассогласование.

var 
    count: DWORD; 
begin 
    count := 3/1.6; 
    Writeln(inttostr(count)); 

Так я либо должны округлить count := round(3/1.6) что приводит к:

или TRUNC count := trunc(3/1.6) что приводит к

Действительно ли это уловка? Возможно, есть переключатель компилятора, который мне нужно было бы переключить?

Вы могли бы подумать, что это легко для Google, но, поверьте, это не так.

Спасибо за ваше время!

+2

Тогда у нас должен быть другой Google. Первый хит для * Дельфий кардинала и расширенного несоответствия * идет [здесь] (http://stackoverflow.com/q/21588915/960757). И это даже не точная ошибка. – TLama

+0

Спасибо @TLama. Итак, согласно документации div - это путь! – MRSNAPS

ответ

3

C/C++ имеет только один оператор арифметического деления - / - но его поведение зависит от типа операндов, которые вы передаете ему. Он может выполнять как целочисленное деление и с плавающей запятой.

Delphi имеет две арифметические операции деления - div для целочисленного деления и / для точки разделения плавающих.

Вашего C++ код выполняет точку разделения плавающим, а затем назначая результат в DWORD, который не является типом с плавающей точкой, так что присваивание отсекает от десятичной точки:

1/1.699999 является 1.764706920415836, который усекает до 1.

В Delphi оператор / возвращает Extended, что является плавающей точкой. В отличие от C/C++, Delphi не позволяет назначать тип с плавающей запятой непосредственно интегральному типу. Вы должны использовать Round() или Trunc().

В этом случае Delphi эквивалент вашей C++ код использовать Trunc():

var 
    count: DWORD; 
begin 
    count := Trunc(3/1.699999); 
    Write(IntToStr(count)); 
1

Проще всего использовать trunc(3 /1.699999)..

Другим способом является использование предыдущего умножения перед делением.

var 
    count: DWORD; 
begin 
    count := 3; 
    count := (count*1000000) div 1699999; 
    Writeln(inttostr(count)); 

Конечно, чтобы избежать переполнения, count < должен быть maxInt div 1000000.

+1

В целом, этот подход не гарантирует получение одинаковых ответов. Потому что 1.699999 не является точно представимым. –

+0

@DavidHeffernan "идентичные ответы" на что? С математикой с плавающей запятой? Да, конечно, это так же хорошо спроектировано: здесь используется целочисленная математика, поэтому иногда с ней легче работать, особенно, чтобы избежать медленных преобразований x87 под Delphi 32 бит. Я просто хотел показать еще один способ делать деления на целочисленные значения, прецизионный сейф (1699999 точно представлен, когда применяется к мультипликатору 1000000), с чистыми целыми операциями и избегая работать с поплавками. Это известный и используемый трюк во множестве алгоритмов реализации: не используйте float, если они вам не нужны. –

+0

Это моя точка зрения. Они разные. –